๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
React

TanStack Query(react-query) v5 ์ฃผ์š” ๋ณ€๊ฒฝ์  ์•Œ์•„๋ณด๊ธฐ feat. Suspense, ErrorBoundary

by LasBe 2024. 3. 13.
๋ฐ˜์‘ํ˜•

๐Ÿ“’ react-query v5 ์ฃผ์š” ๋ณ€๊ฒฝ์  ์•Œ์•„๋ณด๊ธฐ


์ƒˆ๋กœ์šด ํ”„๋กœ์ ํŠธ์— ์ƒ๊ฐ์—†์ด react-query๋ฅผ ์„ค์น˜ํ•˜๊ณ  ์˜ˆ์ „ ๋ฐฉ์‹ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋ ค๋Š”๋ฐ ์—ฌ๊ธฐ์ €๊ธฐ ์˜ค๋ฅ˜๊ฐ€ ๋นต๋นต ํ„ฐ์ ธ๋‚˜๊ฐ”์Šต๋‹ˆ๋‹ค.

์™œ์ด๋Ÿฌ์ง€ ์‹ถ์–ด package.json์„ ์ฐพ์•„๋ณด๋‹ˆ ๋ฉ”์ด์ € ๋ฒ„์ „์ด ์—…๋ฐ์ดํŠธ ๋˜์—ˆ๊ณ ,
๊ณต์‹๋ฌธ์„œ๋ฅผ ์ฒœ์ฒœํžˆ ํ›‘์–ด๋ณด๋‹ˆ ์ƒ๊ฐ๋ณด๋‹ค ์‚ฌ์šฉ ๋ฐฉ์‹์ด ๋ณ€๊ฒฝ๋œ ๊ฒƒ์ด ๋งŽ์•„ ์ฃผ์š” ๋ณ€๊ฒฝ์ ๋“ค์„ ์งš๊ณ  ๋„˜์–ด๊ฐ€๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๐Ÿ“Œ hook ์˜ต์…˜ ๊ฐ์ฒด ํ˜•ํƒœ๋กœ ๋ณ€๊ฒฝ

๋ฒ„์ „์ด ์˜ฌ๋ผ๊ฐ€๋ฉฐ ํ›…์— ์˜ต์…˜์„ ๋„ฃ์–ด์ฃผ๋Š” ๋ฐฉ์‹์ด ๊ฐ์ฒด ํ˜•ํƒœ๋กœ ๋ฐ”๋€Œ์–ด ๋”์šฑ ์ง๊ด€์ ์ธ ๋ชจ์Šต์„ ๋ณด์ž…๋‹ˆ๋‹ค.

  • ๊ธฐ์กด ์‚ฌ์šฉ ๋ฐฉ์‹
const { data } = useQuery(['queryKey'], getData);
const mutation = useMutation(setData);

 

  • ๋ณ€๊ฒฝ ํ›„ ์‚ฌ์šฉ ๋ฐฉ์‹
const { data } = useQuery({ queryKey: ['queryKey'], queryFn: getData });
const mutation = useMutation({ mutationKey: ['mutationKey'], mutationFn: setData })

 

๐Ÿ“Œ Suspense ํŠธ๋ฆฌ๊ฑฐ ์˜ต์…˜ ๋ณ€๊ฒฝ

  • ๊ธฐ์กด ์‚ฌ์šฉ ๋ฐฉ์‹
const { data } = useQuery(['queryKey'], getData, { suspense: true });

// or
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      suspense: true
    },
  },
});

๊ธฐ์กด์—๋Š” queryClient์— suspense: true ๊ธฐ๋ณธ ์˜ต์…˜์„ ๋ถ€์—ฌํ•˜๋˜๊ฐ€, useQuery ํ›…์— ๋ณ„๋„์˜ ์˜ต์…˜์„ ์ฃผ์–ด suspense๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•  ์ˆ˜ ์žˆ์—ˆ์ง€๋งŒ ์ด์ œ๋Š” Suspense๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ hook์ด ๋ณ„๋„๋กœ ์ถœ์‹œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

  • ๋ณ€๊ฒฝ ํ›„ ์‚ฌ์šฉ ๋ฐฉ์‹
const { data } = useSuspenseQuery({ queryKey: ['queryKey'], queryFn: getData });

์ด์ œ๋Š” Suspense๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด query hook์— ์˜ต์…˜ ๋Œ€์‹  useSuspenseQuery ๋ฅผ ์ด์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

๐Ÿ“Œ Suspense์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•˜๋Š” enabled ์˜ต์…˜

  • ๊ธฐ์กด ์‚ฌ์šฉ ๋ฐฉ์‹
const { data } = useQuery(['queryKey'], getData, { suspense: true, enabled: false });

๊ธฐ์กด์—๋Š” useQuery์— suspense์™€ enabled ์˜ต์…˜์„ ๋™์‹œ์— ๋ถ€์—ฌํ•ด ํŠน์ • ๊ฐ’์— ์˜์กด์ ์ธ ์ฟผ๋ฆฌ๋ฅผ ๋™๊ธฐ์ ์œผ๋กœ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

 

  • ๋ณ€๊ฒฝ ํ›„ ์‚ฌ์šฉ ๋ฐฉ์‹
// useQuery๋Š” enabled ์‚ฌ์šฉ ๊ฐ€๋Šฅ
const { data } = useQuery({
  queryKey: ['queryKey'],
  queryFn: getData,
  enabled: false,
});

// useSuspenseQuery๋Š” enabled ์‚ฌ์šฉ ๋ถˆ๊ฐ€
const { data } = useSuspenseQuery({ queryKey: ['queryKey'], queryFn: getData });

์ด์ œ๋Š” suspense์™€ enabled ์˜ต์…˜ ๋‘ ๊ฐ€์ง€๋ฅผ ๋™์‹œ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋„๋ก ๋ณ€๊ฒฝํ–ˆ์Šต๋‹ˆ๋‹ค.

์œ„ Omit ์œ ํ‹ธ๋ฆฌํ‹ฐ ํƒ€์ž…์€ ๋’ค union of string์œผ๋กœ ๋ฐ›์€ keys๋ฅผ ์ œ์™ธํ•œ ํƒ€์ž…์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

์ฆ‰, useSuspenseQuery ํ•จ์ˆ˜์— enabled ํƒ€์ž…์„ ์ œ์™ธํ–ˆ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.

 

๊ฐœ๋ฐœ์ง„๋“ค์˜ ์ƒ๊ฐ์„ ์ •ํ™•ํ•˜๊ฒŒ ์•Œ ์ˆœ ์—†์ง€๋งŒ ์œ ์ถ”ํ•˜๊ธฐ๋กœ๋Š” ์„ฑ๊ณตํ•œ ์ƒํƒœ ๋ถ„๋ฆฌ๋ฅผ ์œ„ํ•ด ํƒ„์ƒํ•œ Suspense์˜ ์—ญํ• ์„ ๋” ๊ฒฌ๊ณ ํžˆ ํ•˜๋ ค๋Š” ์˜๋ฏธ๊ฐ€ ์žˆ์ง€ ์•Š์„๊นŒ ํ•ฉ๋‹ˆ๋‹ค.

 

๐Ÿ“Œ ErrorBoundary ํŠธ๋ฆฌ๊ฑฐ ์˜ต์…˜ ๋ณ€๊ฒฝ

  • ๊ธฐ์กด ์‚ฌ์šฉ ๋ฐฉ์‹
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      suspense: true,
      useErrorBoundary: true,
    },
  },
});

๊ธฐ์กด์—๋Š” suspense ์˜ต์…˜์„ ๋ถ€์—ฌํ•˜๊ฑฐ๋‚˜, ๋ณ„๋„๋กœ useErrorBoundary ์˜ต์…˜์„ ๋ถ€์—ฌํ•˜๋ฉด ErrorBoundary๋กœ ์—๋Ÿฌ๊ฐ€ ์ „ํŒŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

  • ๋ณ€๊ฒฝ ํ›„ ์‚ฌ์šฉ ๋ฐฉ์‹
const queryClient = new QueryClient({
  defaultOptions: {
    queries: {
      throwOnError: true,
    }
    mutations: {
      throwOnError: true,
    },
  },
});

๋ณ€๊ฒฝ ํ›„์—๋Š” queries์™€ mutations ๊ฐ๊ฐ ์†์„ฑ์— ๋ณ„๋„๋กœ throwOnError ์˜ต์…˜์„ ๋ถ€์—ฌํ•ด์•ผ ์—๋Ÿฌ ์ „ํŒŒ๊ฐ€ ๊ฐ€๋Šฅํ•ด์กŒ์Šต๋‹ˆ๋‹ค.

 

๊ทธ๋Ÿผ ๋ฉ”์ด์ € ๋ฒ„์ „ ์—…๋ฐ์ดํŠธ ๋Œ€์‘์— ๋„์›€์ด ๋˜์—ˆ๊ธธ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€


์˜คํ”ˆ ์ฑ„ํŒ