React query - TEAM-ARK/inflearn-clone-front GitHub Wiki

Part 1 - Queries

React-query

  • ๋ฐ์ดํ„ฐ fetching ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ
  • props๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ๋ฐ์ดํ„ฐ์˜ ์บ์‹ฑ์ด ๊ฐ€๋Šฅ
  • infinite ์ฟผ๋ฆฌ ์ œ๊ณต
  • mutation์„ ์‚ฌ์šฉํ•˜์—ฌ ์บ์‹œ๋ฅผ ์ง์ ‘ ๊ด€๋ฆฌ
  • dev tool ์ œ๊ณต

React-query with nextjs

const reactQueryClient = new QueryClient({
  defaultOptions: {
    queries: {
      staleTime: 5 * 1000,
    }
  }
})

const MyApp: FC<AppProps> = ({ Component, pageProps }): AppProps) => {
  return (
    <QueryClientProvider client={reactQueryClient}>
      <ReactQueryDevtools initialIsOpen={false} />
      <Component {...pageProps} />
    </QueryClientProvider>
  )
}
  • nextjs์—์„œ react-query ์‚ฌ์šฉ์‹œ _app.js ํŽ˜์ด์ง€๋ฅผ QueryClientProvider๋กœ ๊ฐ์‹ธ์•ผ ํ•œ๋‹ค
  • ReactQueryDevtools๋กœ ๊ฐ์‹ธ๋ฉด dev tools์˜ ์‚ฌ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค
    • ๋ธŒ๋ผ์šฐ์ € ์•„๋ž˜์— ๊ฝƒ ๋ชจ์–‘์ด ์ƒ๊ธฐ๋ฉฐ ๋ˆ„๋ฅด๋ฉด dev tools๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ์˜ ์ถ”์  ๋ฐ ์บ์‹ฑ ์—ฌ๋ถ€์˜ ํ™•์ธ์ด ๊ฐ€๋Šฅํ•˜๋‹ค
    • key์˜ ๊ฐ’์— ๋”ฐ๋ผ ์–ด๋– ํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์žˆ๋Š”์ง€ ํ™•์ธ์ด ๊ฐ€๋Šฅํ•˜๋‹ค

React-query์˜ 3๊ฐ€์ง€ ์ฃผ์š” ๊ธฐ๋Šฅ

  1. queries: ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์˜ค๊ธฐ ์œ„ํ•œ ๊ธฐ๋Šฅ
  2. mutation: post/update/delete์˜ ์š”์ฒญ์„ ์œ„ํ•œ ๊ธฐ๋Šฅ
  3. queries cache: ๋ฐ์ดํ„ฐ ์บ์‹ฑ
  • staleTime: ๊ธฐ๋ณธ ์ฟผ๋ฆฌ๊ฐ€ stale ์ƒํƒœ๊ฐ€ ๋˜๊ธฐ๊นŒ์ง€ ์†Œ์š”๋˜๋Š” ์‹œ๊ฐ„, default๋Š” ๋ฐ”๋กœ stale ์ƒํƒœ๋กœ ๋ณ€ํ•จ
  • cacheTime: inactive ์ฟผ๋ฆฌ๊ฐ€ ์บ์‹œ์—์„œ๋ถ€ํ„ฐ ์‚ญ์ œ๋˜๊ธฐ๊นŒ์ง€ ์†Œ์š”๋˜๋Š” ์‹œ๊ฐ„, default๋Š” 5๋ถ„
    • inactive: ์บ์‹ฑ๋˜์–ด ์žˆ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์‚ฌ์šฉ๋˜๊ณ  ์žˆ์ง€ ์•Š์„ ๊ฒฝ์šฐ inactive ์ƒํƒœ๊ฐ€ ๋œ๋‹ค -> ์บ์‹œ ๋ฐ์ดํ„ฐ์˜ ์‚ฌ์šฉ ์—ฌ๋ถ€ ํ™•์ธ
    • stale: stale ์ƒํƒœ๊ฐ€ ๋˜๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ๋” ์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•˜๋ฉฐ re-fetch๋ฅผ ํ•ด์•ผ ์‚ฌ์šฉ ํ•  ์ˆ˜ ์žˆ๋‹ค -> re-fetch์˜ ํ•„์š” ์—ฌ๋ถ€ ํ™•์ธ
// get request
const { isLoading, isError, error, data }: UseQueryResult<IPerson, Error> = useQuery<IPerson, Error, IPerson, string>(
  'person', // query key
  async () => {
    const res = await fetch('/api/person');
    return res.json();
  }, {
    staleTime: 5 * 1000,
    cacheTime,
    select: (person) => person.name // ์›ํ•˜๋Š” person ๋ฐ์ดํ„ฐ๋งŒ ์‘๋‹ต์œผ๋กœ ๋„˜๊ธธ ์ˆ˜ ์žˆ์Œ, 3๋ฒˆ์งธ ํƒ€์ž…์„ string์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ค˜์•ผ ํ•จ
    // ๋ณดํ†ต์€ ์„ค์ •ํ•˜์ง€ ์•Š๊ณ  default๋กœ ์‚ฌ์šฉํ•จ
  }
);

if (isLoading) {
  return (
    <div>
      <p>Loading...</p>
    </div>
  )
}

if (isError) return <p> Error is {error?.message}</p>;

return (
  <>
    <p>{data?.id}</p>
    <p>{data?.name}</p>
    <p>{data?.age}</p>
  </>
)
  • query data์— 'person'๊ณผ ๊ฐ™์€ ํŠน๋ณ„ํ•œ key๋ฅผ ์ง€์ • ํ•  ์ˆ˜ ์žˆ๋‹ค( cache key)
  • ์ฟผ๋ฆฌ๊ฐ€ ์‹คํ–‰ ๋  ๋•Œ ๋ฐ์ดํ„ฐ๊ฐ€ ๊ฐ™์€ ๊ฒฝ์šฐ ์บ์‹ฑ์ด ๋˜๋ฉฐ ๋‹ค๋ฅผ ๊ฒฝ์šฐ ์ƒˆ๋กœ์šด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜จ๋‹ค
  • ์ฟผ๋ฆฌ key๋Š” string์ด ์•„๋‹Œ array๋กœ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค
    • dynamic page์˜ ๊ฐ ํŽ˜์ด์ง€์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃฐ ๋•Œ ['todos', 5]์ด์™€ ๊ฐ™์ด ์„ค์ •์ด ๊ฐ€๋Šฅํ•˜๋‹ค
  • page์— ์ ‘๊ทผ ํ•  ๋•Œ ๋งˆ๋‹ค react-query๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ fetch ํ•ด์ค€๋‹ค
    • ์—ฌ๋Ÿฌ ํŽ˜์ด์ง€๋ฅผ ๋ธŒ๋ผ์šฐ์ €์— ์ผœ ๋†“์€ ๊ฒฝ์šฐ ๋‹ค๋ฅธ ํŽ˜์ด์ง€์— ์žˆ๋‹ค๊ฐ€ ํƒญ์„ ๋ˆŒ๋Ÿฌ ์ ‘์†ํ•˜๋ฉด re-fetch๋ฅผ ์ž๋™์œผ๋กœ ์‹คํ–‰ํ•œ๋‹ค
  • staleTime๊ณผ ๊ฐ™์€ ์˜ต์…˜์„ ์ „์—ญ์—์„œ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ _app.js์—์„œ ์ •์˜ํ•œ QueryClient ๊ฐ์ฒด ์ธ์Šคํ„ด์Šค์—์„œ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ’์œผ๋กœ ๋„ฃ์œผ๋ฉด ๋œ๋‹ค
const fetchPerson = async (): Promise<IPerson> => {
  const res = async fetch('/api/person');
  // need to do this with fetch since doesn't automatically throw errors axios and graphql-request do
  if (res.ok) { // 200 response
    return res.json();
  }
  throw new Error('Network response not ok'); // need to throw because react-query functions need to have error throw
}

const { isLoading, isError, error, data }: UseQueryResult<IPerson, Error> = useQuery<IPerson, Error, IPerson, string>(
  'person', // query key
  fetchPerson
  • fetch๋ฅผ ์ •์˜ํ•˜๋Š” ๋ถ€๋ถ„์€ ๋ณดํ†ต fetchPerson๊ณผ ๊ฐ™์ด ํ•จ์ˆ˜๋กœ ๋”ฐ๋กœ ์ •์˜ํ•œ๋‹ค
    • fetch๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  axios๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด try / catch ๋ฌธ์œผ๋กœ ์ •์˜๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‹ค

dynamic page์—์„œ์˜ react-query

const getPersonById = async(id: string | string[] | undefined): Promis<IPerson> => {
  if (typeof id === 'string') {
    const res = await fetch(`/api/person/${id}`);
    if(res.ok) {
      return res.json();
    }		
    throw new Error('error fetching user with id');
  }
  throw new Error('invalid id');
}

const PersonPage: FC = () => {
  const {
    query: { id },
  } = useRouter();

  const { isLoading, isError, error, data } = useQuery<IPerson, Error>(['person', id], () => getPersonById(id), {
    enabled: !!id, // enabled will stop a query from running, so will only call when id is available (dependent queries)
  });
}

if (isLoading) {
  return (
    <div>
      <p>Loading...</p>
    </div>
  )
}

if (isError) return <p> Error is {error?.message}</p>;

return (
  <>
    <p>{data?.id}</p>
    <p>{data?.name}</p>
    <p>{data?.age}</p>
  </>
)
  • react-query์˜ key๋Š” ๊ฐ ํŽ˜์ด์ง€์—์„œ ์ž์‹ ๋งŒ์˜ key๋ฅผ ๊ฐ€์ง„๋‹ค
  • ํ•จ์ˆ˜์— ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋„˜๊ธฐ๊ณ  ์‹ถ์„ ๊ฒฝ์šฐ์—๋Š” ์ฝœ๋ฐฑํ•จ์ˆ˜๋กœ ๋„˜๊ธด๋‹ค
  • enabled๊ฐ€ false์ผ ๊ฒฝ์šฐ react-query๊ฐ€ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค
  • ํŽ˜์ด์ง€ ์•ˆ์— ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ๊ณ  ํŽ˜์ด์ง€์™€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๊ฐ™์€ key๋ฅผ ๊ฐ€์งˆ ๊ฒฝ์šฐ ์ฟผ๋ฆฌ๊ฐ€ 2๋ฒˆ ๋ถˆ๋ฆฌ์–ด์ง„๋‹ค. staleTime์„ ์„ค์ •ํ•ด ๋†“์œผ๋ฉด ์บ์‹ฑ ๋œ ๊ฐ’์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ํ•œ ๋ฒˆ๋งŒ ๋ถˆ๋ฆฌ์–ด์ง„๋‹ค
  • retry ์˜ต์…˜์ด ์žˆ์œผ๋ฉฐ default๋Š” 3์ด๋‹ค. ์„œ๋ฒ„์˜ ํ†ต์‹ ์ด ์‹คํŒจํ•œ ๊ฒฝ์šฐ ๋ช‡ ๋ฒˆ๊นŒ์ง€ ์žฌ์‹œ๋„๋ฅผ ํ• ์ง€ ์„ค์ •ํ•˜๋Š” ์˜ต์…˜์ด๋‹ค. retryTime์œผ๋กœ ๋ช‡ ์ดˆ๋งˆ๋‹ค ์‹คํ–‰ํ• ์ง€๋„ ์„ค์ •์ด ๊ฐ€๋Šฅํ•˜๋‹ค
  • ํ•œ ์ปดํฌ๋„ŒํŠธ์—์„œ react-query๋ฅผ ์—ฌ๋Ÿฌ๊ฐœ ์‚ฌ์šฉ ํ•  ๊ฒฝ์šฐ ๋น„๋™๊ธฐ๋กœ ๋™์ž‘ํ•œ๋‹ค
const id = useQuery(getUserId);

const { isLoading, isError, error, data } = useQuery<IPerson, Error>(['person', id], () => getPersonById(id), {
  enabled: !!id,
});
  • depending query๋Š” ์ฟผ๋ฆฌ๋ฅผ ๋™๊ธฐ์ ์œผ๋กœ ๋™์ž‘ํ•˜๊ณ  ์‹ถ์„๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. ์œ„์™€ ๊ฐ™์ด ์„ค์ •ํ•˜๋ฉด ์ฒซ ๋ฒˆ์งธ useQuery ํ›…์ด ์‹คํ–‰๋˜๊ธฐ๊นŒ์ง€ ๋‘ ๋ฒˆ์งธ ํ›…์€ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š”๋‹ค

์ฐธ๊ณ 

React tutorial

React query ์„œ๋ฒ„ ์ƒํƒœ ๊ด€๋ฆฌ

โš ๏ธ **GitHub.com Fallback** โš ๏ธ