pebblepark
개발계발
pebblepark
전체 방문자
오늘
어제
  • 분류 전체보기 (24)
    • Frontend (7)
    • Backend (7)
    • 인프라 (1)
    • CS (0)
      • Design Pattern (0)
    • 정리용 (9)
    • 회고 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • SpringMVC
  • @ModelAttribute
  • springboot
  • 무한스크롤
  • 스프링
  • useLayoutEffect
  • vite
  • Github Pages
  • Docker
  • wsl
  • React Query
  • typescript
  • github
  • react-query
  • 스프링 컨테이너
  • CORS
  • ERR_UNSAFE_PORT
  • hoisting
  • 호이스팅
  • 스프링 의존관계
  • redux
  • 스프링 빈
  • 리액트쿼리
  • spring
  • javascript
  • debounce
  • Context API
  • react
  • TDZ
  • Git

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
pebblepark

개발계발

React Query의 InvalidateQueries가 동작하지 않을 때
정리용

React Query의 InvalidateQueries가 동작하지 않을 때

2022. 9. 14. 12:51

문제상황

생성 API를 호출한 뒤 성공한 경우 invalidateQueries 를 통해 기존에 조회했던 쿼리를 무효화시키고 데이터를 새로 조회해오고자 했다.

React Query DevTools를 통해 쿼리 조회 결과를 살펴보면 다음과 같다.

  1. 맨 처음에 ["PRODUCTS",false] 쿼리를 먼저 조회하였다.
    • 해당 컴포넌트가 unmount 되면서 해당 쿼리 결과는 inactive 상태가 되었다.

  1. 이후 ["PRODUCTS",true] 쿼리를 조회하여 현재 fresh 상태의 쿼리 결과를 가지고 있다.

 

이후 Product 리스트에 새 상품을 추가하면서 해당 쿼리 결과를 업데이트 시킬 필요가 있었고, 아래 두 가지의 방법 중 후자의 방법으로 업데이트를 처리하고자 했다.

1️⃣ 낙관적 업데이트 처리
2️⃣ 쿼리를 무효화 시켜 다시 조회

따라서 다음과 같이 invalidateQueries를 사용하였지만 결과는 아래와 같았다.

queryClient.invalidateQueries("PRODUCTS")

 

fresh 상태에 있었던 ["PRODUCTS",true] 쿼리는 Last Updated를 통해 변경이 성공적으로 이루어졌음을 확인할 수 있다.

Last Updated: 오후 10:53:55 → 오후 10:57:26

 

"PRODUCTS"를 쿼리 키를 가지고 있는 쿼리들을 무효화시켰기 때문에 ["PRODUCTS",false] 쿼리 또한 위와 같이 업데이트 되면서 Last Updated가 변경되었어야 했지만 아래 사진과 같이 변경이 이루어지지 않았다.

Last Updated: 오후 10:53:51 → 오후 10:53:51

 

참고

공식문서를 살펴보면 invalidateQueries 의 쿼리 매칭은 다음과 같다.
쿼리 무효화의 범위가 쿼리 키 범위의 상위에서 하위로 전파된다고 생각하면 된다.

  1. 해당 쿼리 키로 시작하는 모든 쿼리 무효화
import { useQuery, useQueryClient } from '@tanstack/react-query'

const queryClient = useQueryClient()

// 'todos'로 시작하는 쿼리키를 가지고 있는 모든 쿼리 무효화  
queryClient.invalidateQueries(\['todos'\])

// 따라서 아래의 쿼리들은 모두 무효화 된다  
const todoListQuery = useQuery(\['todos'\], fetchTodoList)  
const todoListQuery = useQuery(\['todos', { page: 1 }\], fetchTodoList)
  1. 구체적인 쿼리 키(하위 키)를 전달하여 특정 변수가 있는 쿼리만 무효화
// { type: 'done' } 과 같이 구체적인 쿼리키 전달
queryClient.invalidateQueries(['todos', { type: 'done' }])

// 해당 쿼리는 무효화 된다
const todoListQuery = useQuery(['todos', { type: 'done' }], fetchTodoList)
const todoListQuery = useQuery(['todos', { type: 'done' }, { page: 1 }], fetchTodoList)

// 해당 쿼리는 무효화 되지 않는다
const todoListQuery = useQuery(['todos'], fetchTodoList)
  1. 하위 키가 없는 쿼리만 무효화
// invalidateQueries 호출 시 두 번째 인자로 { exact: true } 전달
queryClient.invalidateQueries(['todos'], { exact: true })

// 해당 쿼리는 무효화 된다  
const todoListQuery = useQuery(['todos'], fetchTodoList)

// ['todos'] 쿼리 키의 하위 키(['todos' { type: 'done' }])을 가지고 있으므로  
// 해당 쿼리는 무효화 되지 않는다  
const todoListQuery = useQuery(['todos', { type: 'done' }], fetchTodoList)

 

해결

Stack Overflow의 해당 답변을 참고하였다.

React Query를 설정할 때 기본 옵션으로 주어지는 refetch 옵션 중 refetchOnMount를 false로 설정해두어서 발생한 일이었다.

 React Query의 refetch 관련 기본 옵션
  • refetchOnMount: 마운트됨
  • refetchOnWindowFocus: 창에 다시 초점 맞춤
  • refetchOnReconnect:네트워크 재연결

 

["PRODUCTS",false]에 해당하는 쿼리는 해당 쿼리를 호출하는 컴포넌트가 unmount 되면서 inactive 상태였기 때문에 invalidateQueries가 동작하지 않았다.

따라서 다음과 같이 { refetchInactive: true } 를 통해 해결하였다.

queryClient.invalidateQueries(QueryKeys.PRODUCT, { refetchInactive: true });

 

저작자표시 (새창열림)

'정리용' 카테고리의 다른 글

useLayoutEffect  (0) 2022.09.22
[React] 일정시간동안 이벤트 발생이 없으면 콜백 함수 실행  (0) 2022.08.09
크롬에서 막혀있는 포트  (0) 2022.07.01
Proxy 서버로 CORS 해결하기  (0) 2022.06.24
Docker 명령어 정리  (0) 2022.05.25
    '정리용' 카테고리의 다른 글
    • useLayoutEffect
    • [React] 일정시간동안 이벤트 발생이 없으면 콜백 함수 실행
    • 크롬에서 막혀있는 포트
    • Proxy 서버로 CORS 해결하기
    pebblepark
    pebblepark
    프론트엔드 개발자입니다. 피드백은 언제나 환영입니다:)

    티스토리툴바