기존 테이블 컴포넌트에 정렬 API를 연동하는 작업을 하던 중 다음과 같은 상황을 만났다.
(간단한 예제 코드를 만들어 보고자 했으나 공개 API로 같은 현상을 재현하기가 어려웠다 😢)
먼저 테이블은 antd의 table 컴포넌트로 테이블의 각 열마다 정렬 버튼이 있다. 정렬 버튼을 처음 누르면 오름차순 정렬(ascend), 두번째로 누르면 내림차순 정렬(descend), 세번째로 누르면 정렬 취소 순서로 동작하고, 사용자가 특정 열의 정렬 버튼을 누를 때마다 해당 열이 ascend인지 descend인지 알 수 있다. 이 정보를 바탕으로 서버에 쿼리 스트링으로 정렬된 데이터를 요청한다.
그러자 특정 열의 정렬 버튼을 누를 때마다 화면이 full refresh가 되었다...! 😰 정렬 버튼을 한번씩 눌러서 데이터가 캐시가 된 다음부터는 정렬 버튼을 눌러도 화면이 refresh 되지 않고 원하는 대로 동작했다.
antd table 컴포넌트의 ajax 데모 예제에서는 useEffect 안에서 데이터를 패치하는 방식인데, 위의 코드를 useQuery를 사용하지 않고 useEffect 에서 fetchData()를 하니 정렬 버튼을 눌렀을 때 full refresh 없이 정상 작동하는 것을 확인했다.
그렇다면 이것은 table 컴포넌트의 문제가 아닌, useQuery를 사용하면서 발생하는 문제렸다... 왜 그런지 찬찬히 살펴보니 react-query의 useQuery에서 queryKey에 ordering 항목이 포함되어 있기 때문에 ordering 정보가 바뀔 때마다 새로운 데이터를 받으면서 컴포넌트가 리렌더링되기 때문이었다.
tanstack의 query 레포에 관련 이슈가 있었다.
Use react query in table with sorting and filtering #1113
https://github.com/TanStack/query/discussions/1113
tanstack query의 메인테이너인 TkDodo의 코멘트에서 힌트를 얻을 수 있었다.
it just utilizes keepPreviousData, which, according to the docs, does:
"If set, any previous data will be kept when fetching new data because the query key changed."
so I think you can just implement paging and sorting alike with that and have your state change the queryKey :)
const { data } = useQuery<ProjectsQueryResult>({
queryKey: [
"projects",
{ page: tableParams.pagination.current },
{ ordering },
],
queryFn: () =>
fetcher({
page: tableParams.pagination.current,
ordering,
}),
keepPreviousData: true // 추가
});
+) 사족
keepPreviousData 옵션은 react-query의 v8에서는 사라졌다. 프로젝트에서는 v7을 사용하고 있어서 keepPreviousData 설정을 추가해서 문제를 해결할 수 있었다.
'돌멩이 하나 > 에러는 미래의 연봉' 카테고리의 다른 글
무한 스크롤 이슈 디버깅 과정 (0) | 2024.07.27 |
---|---|
Checkbox 컴포넌트를 만들면서 알게 된 것들 (0) | 2024.05.22 |
React ErrorBoundary와 react-query를 사용하여 예외 처리 설계하기 (0) | 2024.03.10 |
React의 key에 index를 사용하면 안 되는 이유 (feat. 무한스크롤) (0) | 2024.02.25 |
ant design과 tailwind css 충돌 이슈 해결 (0) | 2023.09.04 |