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

[ React Query ] 게시물에 따른 comments 업데이트

by CODESIGN 2023. 1. 21.

React Query에서 데이터가 만료되었다는 뜻은?


  • 데이터 refatching 실행에는 만료된 데이터 외에도 여러 트리거가 있다.
    • 컴포넌트가 다시 마운트 되거나 윈도가 다시 포커스 되었을 때
    • 만료된 데이터일 경우에만 refatching이 실행된다.
      • staleTime translates to ‘max age’
      • 데이터가 만료됐다고 판단하기 전까지 허용하는 시간. 웹사이트에 표시된 데이터가 10초까지는 그대로여도 괜찮다면 staleTime을 10초로 설정한다.

 

 

staleTime의 기본 값이 0인 이유


데이터는 항상 만료 상태이므로 서버에서 다시 가져와야 한다고 가정한다는 뜻이다.

 

 

게시물에 따른 comments 업데이트


문제: 게시물에 따른 comments가 업데이트 되지 않는다.


첫 번째 게시물의 comments들이 다른 게시물을 눌러도 똑같이 나온다. 그 이유는 쿼리 키에 있다.

쿼리 개발자 도구를 보면, 어떤 게시물을 클릭해 봐도 업데이트되지 않는다. 데이터는 만료(stale)되었고 리페칭(refetching)도 하지 않았다.

 

이유 


모든 쿼리가 comments 쿼리 키를 동일하게 사용하고 있기 때문이다.

이렇게 comments 같이 알려진 쿼리 키가 있을 때는 어떠한 트리거가 있어야만 데이터를 다시 가져오게 된다.

 

댓글의 경우에는 익명 함수를 써서 post.id를 입력해줘야 한다.

 

 

방법


  1. 새 블로그 게시물 제목을 클릭할 때마다 데이터를 무효화시켜서 데이터를 다시 가져오게 만들 수 있다. 하지만 간단한 방법이 아니고 좋은 방법이 아니다.
    1. 데이터를 제거해서는 안된다.안 된다. 블로그 게시물 2의 댓글에 대한 쿼리를 만들 때, 캐시에서 블로그 게시물 1의 댓글을 제거하면 안된다.
    2. 같은 쿼리를 실행하는게 아니므로 같은 캐시 공간을 차치하지 않기 때문이다.
  2. 쿼리는 게시물 ID를 포함하기 (이 방법으로 구현)

 

 

PostDetail.jsx 


comments를 배열로 post.id와 함께 넘겨준다.

import { useState } from 'react';
import { useQuery } from 'react-query';
import { PostDetail } from './PostDetail';

const maxPostPage = 10;

async function fetchPosts(pageNum) {
  // * page=0으로 page 0을 가져오라고 hard coding 되어있다.
  // const response = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=10&_page=0');
  const response = await fetch('https://jsonplaceholder.typicode.com/posts?_limit=10&_page=${pageNum}');
  return response.json();
}

export function Posts() {
  //* useState(0)을 1로 바꿈
  const [currentPage, setCurrentPage] = useState(1);
  const [selectedPost, setSelectedPost] = useState(null);

  // * posts에 currentPage 배열로 추가
  // const { data, isError, isLoading } = useQuery('posts', fetchPosts, { staleTime: 2000 });
  // 아래는 쿼리 키에 currentPage를 포함한것이다. 이제 currentPage 상태가 바뀌면 리엑트 쿼리가 바뀐 쿼리 키를 감지해서 새 쿼리 키에 대한 데이터를 업데이트한다.
  const { data, isError, error, isLoading } = useQuery(['posts', currentPage], () => fetchPosts(currentPage), { staleTime: 2000 });
  // * 위 코드를 보면 이제 useQeury([배열에 currentPage])가 바뀌면 () => fetchPosts(currentPage)함수도 바뀌어서 데이터가 바뀌게 된다.
  // * 한마디로 쿼리 키가 바뀌면 useQuery에 새로운 쿼리를 알려줘서 데이터를 다시 가져오도록 한다.
  if (isLoading) return <h3>Loading...</h3>;
  if (isError) return <h3>Oops, something</h3>;
  return (
    <>
      <ul>
        {data.map((post) => (
          <li key={post.id} className='post-title' onClick={() => setSelectedPost(post)}>
            {post.title}
          </li>
        ))}
      </ul>
      <div className='pages'>
        {/** currentPage가 이보다 같거나 작을때는 전페이지로 가는 버튼 비활성화 */}
        <button
          disabled={currentPage <= 1}
          onClick={() => {
            setCurrentPage((previousValue) => previousValue - 1);
          }}
        >
          Previous page
        </button>
        <span>Page {currentPage}</span>
        <button
          disabled={currentPage >= maxPostPage}
          onClick={() => {
            setCurrentPage((previousValue) => previousValue + 1);
          }}
        >
          Next page
        </button>
      </div>
      <hr />
      {selectedPost && <PostDetail post={selectedPost} />}
    </>
  );
}

 

 

댓글