본문 바로가기
개발 일지/TIL

[ React Query ] useQuery, isError, isLoading

by CODESIGN 2023. 1. 19.

Cliente State vs. Server State


  • Client state: user’s chosen language or theme.
  • Server state: information stored on server

 

 

React Query, 3가지 키워드


  • Query - 어떤 데이터에 대한 요청을 의미한다.
  • Mutation - 어떤 데이터를 바꾸는(추가, 수정, 삭젝) 것이다.
  • Query Invalidation - 쿼리를 무효화 시킨다. 

 

 

React Query 실행 순서


1. React Query 설정

npm install react-query

2. Create query client: 쿼리와 서버의 데이터 캐시를 관리하는 클라이언트

3. Apply QueryProvider: 자녀 컴포넌트에 캐시와 클라이언트 구성을 제공한다.

4. useQuery: 서버에서 데이터를 가져온다면, run useQuery

 

 

isFetching vs. isLoading


isFetching - async query function hasn’t yet resolved

  • 비동기 쿼리가 해결되지 않았음을 의미한다.
  • 이경우에는 아직 fetching을 완료하지 않았다는 의미지만 쿼리가 Axios 호출 또는 GraphQL 호출일 수도 있다. 이것이 isFetching이다.

isLoading - no cached data, plus isFetching

  • 가져오는 상태에 있음을 의미한다.
  • 쿼리 함수가 아직 해결되지 않은 것이다.
  • 그리고 캐시 된 데이터도 없다. 이 쿼리를 만든 적이 없다는 의미이다. 데이터를 가져오는 중이고 표시할 캐시 데이터도 없다는 것이다.

 

 

렌덤 블로그 글 API로 쿼리 생성 및 로딩


App.jsx


import { Posts } from './Posts';
import './App.css';
import { QueryClient, QueryClientProvider } from 'react-query';

// 클라이언트 생성 - 이제 클라이언트가 있기 때문에 공급자를 추가할 수 있다. 공급자가 클라이언트를 통해 클라이언트가 가지고 있는 캐시와 모든 기본 옵션을 공급자의 자녀 컴포넌트도 사용 할 수 있게 된다.
const queryCleint = new QueryClient();

function App() {
  return (
    // provide React Query client to App
    // 이제 여기 안에는 리액트 쿼리를 사용할 수 있다.

    // Posts안에 써보기.
    <QueryClientProvider client={queryCleint}>
      <div className='App'>
        <h1>Blog Posts</h1>
        <Posts />
      </div>
    </QueryClientProvider>
  );
}

export default App;

 

 

Posts.jsx


import { useState } from 'react';

// 1. import useQuery
// 서버에서 데이터를 가져올 때 사용된다.
import { useQuery } from 'react-query';

import { PostDetail } from './PostDetail';
const maxPostPage = 10;

// 비동기, fetchPosts가 해결될 때까지 아래의 {data}는 useQuery에서 정의되지 않는다.
// useQuery는 fetchPosts가 데이터와 반환되지 않은 경우 데이터에 할당할 항목을 알 수 없기 때문이다.
async function fetchPosts() {
  const response = await fetch('https://jsonplacㄴㅇㄹㅈㄷㄹㄴㅇㄹeholderssdfsf.typicode.com/posts?_limit=10&_page=0');
  return response.json();
}

export function Posts() {
  const [currentPage, setCurrentPage] = useState(0);
  const [selectedPost, setSelectedPost] = useState(null);

  // replace with useQuery
  // 데이터는 더이상 hard coded array가 아닌
  // const data = [];
  
  // 반환 객체에서 useQuery로 데이터 속성을 구조분해한다.
  // useQuery는 다양한 속성을 가진 객체를 반환한다.
  // useQuery(쿼리 키(이름), 쿼리에 대한 데이터를 가져오는 방법)
  const { data, isLoading } = useQuery('posts', fetchPosts);
  // fetchPosts가 완료되면 data에 배열이 포함된다.
  if (isLoading) return <h3>Loading...</h3>;
  return (
    <>
      <ul>
        {data.map((post) => (
          <li key={post.id} className='post-title' onClick={() => setSelectedPost(post)}>
            {post.title}
          </li>
        ))}
      </ul>
      <div className='pages'>
        <button disabled onClick={() => {}}>
          Previous page
        </button>
        <span>Page {currentPage + 1}</span>
        <button disabled onClick={() => {}}>
          Next page
        </button>
      </div>
      <hr />
      {selectedPost && <PostDetail post={selectedPost} />}
    </>
  );
}

 

아래와 같이 데이터의 fetch가 안 끝난 상태에서 Loading... 이 뜨고 fetching이 완료되면 게시물들이 보인다. 

 

 

isError과 error을 추가해 준 뒤 fetch 하는 주소를 조금 바꿔서 에러를 내보았다.

(useQuery는 fetch를 총 3번 시도한 후 loading이 되지 않으면 error을 내보낸다.)

 

import { useState } from 'react';

// 1. import useQuery
// 서버에서 데이터를 가져올 때 사용된다.
import { useQuery } from 'react-query';

import { PostDetail } from './PostDetail';
const maxPostPage = 10;

// 비동기, fetchPosts가 해결될 때까지 아래의 {data}는 useQuery에서 정의되지 않는다.
// useQuery는 fetchPosts가 데이터와 반환되지 않은 경우 데이터에 할당할 항목을 알 수 없기 때문이다.
async function fetchPosts() {
  const response = await fetch('https://jsonplac에러가뜰꺼야eholderssdfsf.typicode.com/posts?_limit=10&_page=0');
  return response.json();
}

export function Posts() {
  const [currentPage, setCurrentPage] = useState(0);
  const [selectedPost, setSelectedPost] = useState(null);

  // replace with useQuery
  // 데이터는 더이상 hard coded array가 아닌
  // const data = [];
  
  // 반환 객체에서 useQuery로 데이터 속성을 구조분해한다.
  // useQuery는 다양한 속성을 가진 객체를 반환한다.
  // useQuery(쿼리 키(이름), 쿼리에 대한 데이터를 가져오는 방법)
  const { data, isError, error, isLoading } = useQuery('posts', fetchPosts);
  // fetchPosts가 완료되면 data에 배열이 포함된다.
  if (isLoading) return <h3>Loading...</h3>;
  if (isError)
    return (
      <>
        <h3>Oops, something went wrong</h3>
        <p>{error.toString()}</p>
      </>
    );
  return (
    <>
     ...
    </>
  );
}

 

 

 

 

 

댓글