[TIL] 22.05.17

kyh·2022년 5월 18일
2

원티드 프리온보딩

목록 보기
9/12

리뷰 내용

  • 조건문, map 함수는 return에서 빼고 함수 혹은 다른 파일로 빼서 분리해주는 것이 좋다.

  • fontawesome 등 현업에서 디자이너와 기획자가 svg, jpg, png 등을 제공하기 때문에 거의 사용하지 않는다.

  • 컴포넌트에 넘기는 Props 인자는 최대 2개, 그 이상은 구조에 문제가 있을 수 있음 => 그것을 줄이는 방안에 대해 고민해볼 것

  • 라이브러리를 이용해서 만들 수 있는 기능은 우선 그 기능 없이 순수하게 날것으로 구현을 몇 번 해보고 로직을 이해한 다음 사용하자

  • 아키텍쳐에 관한 부분은 view에 집중하는 React 자체가 이미 state와 props로 고안된 것이기 때문에 별도로 분류하기 보다는 폴더 구조와 컴포넌트 분리를 잘 해주면 된다. ( Atomic Design Pattern 정도 추가 )


React Query

Server State를 관리하는 라이브러리

1. 사용 목적

  • Server와 Client 사이 비동기 로직들을 쉽게 다루기 위해 사용한다.
  • 캐싱, 동기화, 업데이트를 쉽게 도와준다.

2. React Query의 Life Cycle

  • fresh : 최신 상태 ( Mount, Update하면 데이터 재요청 X )
  • fetching : 데이터 요청 중인 상태
  • stale : 만료되어 업데이트가 필요한 상태, (Mount/Update하면 데이터 재요청)
  • inactive : 현재 사용하지 않는 상태, (특정 시간 경과 후 GC에 의해 제거)
  • delete : GC에 의해 캐시에서 제거된 상태

3. 사용 방법

1) 설치

  • 패키지 매니저를 이용해서 라이브러리를 아래 두 가지 방법 중에 하나를 선택해서 설치한다.
$ npm i react-query # installing with npm

$ yarn add react-query # installing with yarn

2) 초기 설정

  • QueryClient와 QueryClientProvider 최상위 컴포넌트에 위치 시킨다.
    QueryClient 인스턴스 생성 후 QueryClientProvider를 아래와 같이 적용한다.
    • QueryClient : 쿼리와 캐시 관리를 수행한다.
    • QueryClientProvider : QueryClient를 Props로 받고, 자식 컴포넌트들이 이를 사용할 수 있도록 해준다.
// App.jsx
import { QueryClient, QueryClientProvider } from 'react-query';
import Post from './Post';
const queryClient = new QueryClient();

function App() {
	return (
      <QueryClientProvider client={queryClient}>
      	<div className='app'>
          <Post />
        </div>
      </QueryClientProvider>
    );
}

export default App;

3) useQuery

  • 서버에서 데이터를 가져오고 캐싱하기 위한 Hooks
  • uesQuery 인자
    • query key : string과 array를 받으며, 요청에 대한 식별자가 된다. 이 값이 다르면 호출하는 API가 같더라도 캐싱이 별도로 관리된다.
      • array의 경우 0번째 인덱스에 query key를 받고 1번째 인덱스는 query 함수 내부의 매개변수로 전달된다.
    • query Func : API 호출 함수(fetch, axios)를 받으며 Promise를 반환한다.
    • options : uesQuery에 대한 기능 제어한다.
  • useQuery 반환 값
    • data : 서버 요청에 의한 데이터
    • isLoading(boolean) : 캐시가 없을 때, 데이터 요청 중인 상태
    • isFetching(boolean) : 캐시 유무 관계 없이 데이터 요청 중인 상태
    • isError(boolean) : 서버 요청 실패에 대한 상태
      • 에러를 판단하기 위해 추가적으로 3번 요청을 시도하고, 모두 실패하면 true 값을 얻는다.
    • error(object) : 서버 요청 실패에 대한 에러 메시지
import { useQuery } from 'react-query';

function Post () {
  
  const fetchFunc = () => {
    return axios.get('https://something:port/pageName');
  };
  
  // case 1. Destructuring X
  const responseData = useQuery(queryKey, fetchFunc, [,options]);
  // case 2. Destructuring O
  const { data, isLoading, isFetching, isError, error } = ueQuery(queryKey, fetchFunc, [,options]);
  
  if(isLoading) {
   return <span>Loading</span>; 
  }
  
  if(isError) {
   return <span>{error.message}</span> //Request failed with status code 404
  }
  
  return (
    // ...
  ); 
}

export default Post;
  • useQuery 옵션 ( 자주 사용할 만한 )
    • staleTime : fresh 상태에서 stale 상태로 전환되는 시간을 설정하는 옵션으로 데이터의 수명을 설정해서 패치의 주기를 결정한다.
      • API 요청 횟수를 줄일 수 있어서 잘 변하지 않는 컴포넌트에 지정한다.
      • 기본 값 : 0
    • cacheTime : inActive 상태 이후 어느 시점까지 메모리에 데이터를 저장하여 캐싱할 것인지 설정하는 옵션
      • 기본 값 : 300000 => 5min
    • refetchOnMount : 컴포넌트 마운트시 새로운 데이터를 패치할지 설정하는 옵션
      • 기본 값 : true
    • refetchOnWindowFocus : 윈도우가 다시 포커스 되었을 때 새로운 데이터를 패치할지 설정하는 옵션
      • 기본 값 : true
    • refetchInterval : 지정된 데이터 패치 시간을 설정하는 옵션
      • 기본 값 : 0
        • 브라우저 포커스가 없는 경우 실행되지 않음
    • refetchIntervalInBackground : 브라우저에 포커스가 없어도 refetchInterval 옵션이 실행되도록 설정하는 옵션
      • 기본 값 : false
    • initialData : 캐시된 데이터가 없을 때 표시할 초기 값
    • enabled : 컴포넌트가 마운트 되어도 데이터 패치가 일어나지 않도록 설정하는 옵션으로 동기적인 실행을 할 때 사용한다.
      • 기본 값 : true
        • refetch를 이용하여 데이터 패치를 할 수 있음
    • onSuccess : 쿼리 함수가 성공적으로 데이터를 가져왔을 때 호출되는 함수
    • onError : 쿼리 함수에서 오류가 발생했을 때 호출되는 함수
    • select : 데이터 패치 성공 시 원하는 데이터 형식으로 변환
    • keepPreviousData : query key가 변경되어 새로운 데이터를 요청하는 동안에도 마지막 data 값을 유지한다.
      • Pagenation을 구현할 때 캐시되지 않은 페이지를 가져올 때 화면에서 목록이 사라지는 깜빡임 현상을 막을 수 있다.
      • isPreviousData 값으로 현재의 쿼리 키에 해당하는 값인지 확인할 수 있다.
    • 그 외에는 React Query 공식 문서 에서 참조하면 상세하게 확인할 수 있다.
  • 병렬 처리
    • useQuery를 일일히 지정해서 사용할 수도 있지만 많은 쿼리에 대한 처리를 하기 위해서는 useQueries를 이용한다.
const results = useQueries([
  {
    queryKey: ['comments'],
    queryFn: () => fetchComments();
  },
  
  {
   queryKey: ['fruits'],
   queryFn: () => fetchFruits();
  }
]);

4) useMutation

  • 데이터의 변경(추가, 수정, 삭제)하는 경우 사용되는 Hooks
  • useQuery와 차이점
    • query key가 필요하지 않다. (저장 용도 X, query가 아님)
    • isLoading 을 사용한다. (cached 되는 것이 없으므로 isFetching X )
    • 기본 값으로는 에러가 발생 했을 때 재시도하지 않음 (설정으로 변경 가능)
import { useMutation } from 'react-query';

function App() {
   const mutation = useMutation(newTodo => {
     return axios.post('/todos', newTodo)
   })
 
   return (
     <div>
       {mutation.isLoading ? (
         'Adding todo...'
       ) : (
         <>
           {mutation.isError ? (
             <div>An error occurred: {mutation.error.message}</div>
           ) : null}
 
           {mutation.isSuccess ? <div>Todo added!</div> : null}
 
           <button
             onClick={() => {
               mutation.mutate({ id: new Date(), title: 'Do Laundry' })
             }}
           >
             Create Todo
           </button>
         </>
       )}
     </div>
   )
 }
  • useMutation 반환 값
    • isIdle(boolean)
    • isLoading(boolean)
    • isError(boolean)
    • isSuccess(boolean)
    • data
    • error(object)
    • mutate(object) : useMutation의 인자로 넣은 값은 이 object의 속성 값으로 사용할 수 있다.

0개의 댓글