TIL(Today I Learned)/스파르타 내배캠

[TIL] 23/12/06 React 심화: 아웃소싱 프로젝트 (React Query 마스터하기)

개발자먼지 2023. 12. 6. 23:57
반응형

강의듣고, 튜터님 질문하고, 동기 질문하고

마스터 해버림

정리는 못함. 그래서 코드를 첨부하고 주석을 달았다.

TIL

Naver 지역 검색 api 와 함께하는 React Query

내 component  : MapSearch.jsx

function MapSearch() {
  const [inputTitle, setInputTitle] = useState('');
  const [localList, setLocalList] = useState([]);

  // enabled 사용 : false로 두었다가 검색버튼 클릭 시 refatch해서 data 불러옴
  // select 사용 : data에 원래 받아온 데이터에서 items 객체만 선택해서 가져옴
  // isLoading, isError 상태를 유저에게 보여주기 위해 받아옴
  const { isLoading, isError, refetch, data } = useQuery(
    ['local', { local: inputTitle }],
    getLocal,
    { enabled: false, select: (local) => local.items }
  );

  // 검색 버튼 핸들러에서 refetch
  // localList에 저장한 것은 나중에 redux 전역 상태 관리로 변경 예정
  // list 형태의 data 여서... 풀어서 다시 [] 배열에 저장했음, 애초에 왜 []형태로 잡았는가..
  const searchPlaceHandler = async (e) => {
    e.preventDefault();
    const { data } = await refetch();
    console.log('clicked', data);
    setLocalList(...data);
  };

  // input 이벤트 핸들러, 입력값을 저장
  const inputTitleHandler = (e) => {
    setInputTitle(e.target.value);
  };

  return (
    <StyledMap>
      <form onSubmit={searchPlaceHandler}>
        <input
          type="text"
          placeholder="장소를 입력해주세요"
          value={inputTitle}
          onChange={inputTitleHandler}
        />
        <button type="submit">검색</button>
      </form>

      <StListArea>
        {isLoading && <h1>로딩중입니다...!</h1>}
        {isError && <h1>오류가 발생하였습니다..!</h1>}
        {data ? (
          data.map((item, index) => {
            return (
              <StArea key={index}>
                <p>{item.title}</p>
                <p>{item.address}</p>
              </StArea>
            );
          })
        ) : (
          <p>검색을 해주세요</p>
        )}
      </StListArea>
    </StyledMap>
  );
}

 

react query api : local.js

import axios from 'axios';

//주소에는 proxy로 설정해준 주소 뒷부분을 적어주어야 한다.
//component에서 queryKey로 넘겨준 입력값을 첫번째 매개변수에서 찾아서 쿼리로보냈다.
//쿼리에는 결국 검색어가 들어간다.
// 네이버 api를 사용하기위한 key 값 헤더로 넘겨주어야 한다(.env파일에 저장해두었음)
const getLocal = async (input) => {
  const { data } = await axios.get('/v1/search/local.json', {
    params: {
      query: input.queryKey[1].local, 
      display: 5
    },
    headers: {
      'X-Naver-Client-Id': process.env.REACT_APP_LOCAL_CLIENT_ID,
      'X-Naver-Client-Secret': process.env.REACT_APP_LOCAL_CLIENT_SECRET
    }
  });

  return data;
};

export { getLocal };

 

app.js

import { QueryClient, QueryClientProvider } from 'react-query';
import Router from 'shared/Router';

const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: Infinity //TODO : 서버 접근횟수 때문에 임시로 1회만 호출되도록 했다
    }
  }
});

function App() {
  return (
    <QueryClientProvider client={queryClient}>
      <Router />
    </QueryClientProvider>
  );
}

export default App;

 

package.json

"proxy": "https://openapi.naver.com", //를 추가해준다. CORS 에러 방지

 

완성 화면

동영상은 어떻게 찍는지 모르겠고,

css는 아직 안꾸몄고,

data로 넘어온 title을 그대로 찍었더니 검색어에 <b> </b> 가 붙어져 나온다. 후후

 

반응형