Logo

dev-resources.site

for different kinds of informations.

How to used Suspense?

Published at
6/20/2024
Categories
react
suspense
reactquery
Author
hxxtae
Categories
3 categories in total
react
open
suspense
open
reactquery
open
Author
6 person written this
hxxtae
open
How to used Suspense?

React 18๋ถ€ํ„ฐ Suspense๊ฐ€ API ์š”์ฒญ์— ๋”ฐ๋ฅธ loading ์ƒํƒœ๋ฅผ ํ‘œํ˜„ํ• ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค. ๊ทธ์— ๋”ฐ๋ผ react-query, swr ๊ฐ™์€ data fetching ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์—ญ์‹œ Suspense๋ฅผ ์ง€์›ํ•˜๊ณ  ์žˆ๋‹ค. Suspense ์˜ต์…˜๋งŒ true ๋กœ ์„ค์ •ํ•ด์ฃผ๋ฉด, API ์š”์ฒญ์ด ์•Œ์•„์„œ ๋‚ด๋ถ€ ์ฒ˜๋ฆฌ๋ฅผ ํ†ตํ•ด Suspense๋ฅผ ๋™์ž‘์‹œํ‚จ๋‹ค. ์ด๋กœ์จ loading ์ƒํƒœ๋ฅผ ์„ ์–ธ์ ์œผ๋กœ ๋ณด์—ฌ์ค„ ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

์ถ”์ƒํ™”์— ๋Œ€ํ•œ ํŽธ๋ฆฌํ•จ๊ณผ ์‚ฌ์šฉ๋ฒ•์€ ์ธ์ง€ํ•˜๊ณ  ์žˆ์—ˆ์ง€๋งŒ, ์ถ”์ƒํ™”์— ๊ฐ€๋ ค์ง„ Suspense์˜ ๊นŠ์€ ๋™์ž‘ ์›๋ฆฌ์— ๋Œ€ํ•ด์„œ๋Š” ์ธ์ง€ํ•˜์ง€ ๋ชปํ•˜์˜€๋‹ค.

ํ”„๋กœ์ ํŠธ๋ฅผ ํ†ตํ•ด Suspense ์‚ฌ์šฉ์œผ๋กœ ๋กœ๋”ฉ ์„ฑ๋Šฅ์ด ์ €ํ•˜๋˜๋Š” ๊ฒฝํ—˜์„ ํ†ตํ•ด Suspense๊ฐ€ ์–ด๋–ป๊ฒŒ ๋กœ๋”ฉ ์„ฑ๋Šฅ์„ ์ €ํ•˜ ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š”์ง€ ์ด๋ฒˆ ๊ธ€์„ ํ†ตํ•ด ๊ทธ ๋ฌธ์ œ์ ๊ณผ ํ•ด๊ฒฐ์ฑ…์„ ๊ณ ๋ฏผํ•ด ๋ณด์•˜๋‹ค.

data fetching ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ react-query๊ฐ€ ์‚ฌ์šฉ๋˜์—ˆ๋‹ค.
์ •ํ™•ํžˆ ๋งํ•˜๋ฉด data fetching์„ ํŽธ๋ฆฌํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ณ  ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ๋„์™€์ฃผ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ react-query๊ฐ€ ์‚ฌ์šฉ๋˜์—ˆ๋‹ค.

ย 

Use Suspense



function App() {
  return (
    <Suspense fallback={<div>...loading</div>}>
      <TodoList />
    </Suspense>
  );
}

function TodoList() {
  const { data: todoList } = useQuery("todos", () => client.get("/todos"), {
    suspense: true,
  });

  return (
    <div>
      <section>
        <h2>Todo List</h2>
        {todoList?.data.map(({ id, title }) => (
          <div key={id}>{title}</div>
        ))}
      </section>
    </div>
  );
}


Enter fullscreen mode Exit fullscreen mode

์ƒ์œ„์—์„œ Suspense๋กœ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ์‹ธ์ฃผ๊ณ , useQuery ์˜ต์…˜์—์„œ suspense:true๋กœ ์„ค์ •ํ•ด ์ฃผ๊ธฐ๋งŒ ํ•˜๋ฉด fallback์œผ๋กœ Loading ์ƒํƒœ๋ฅผ ๋ Œ๋” ํ•œ๋‹ค. TodoList ์—์„œ API fetch๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ๋™์•ˆ Loading fallback์„ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์ด๋‹ค.

๊ทธ๋Ÿผ Suspense๋Š” ์–ด๋–ป๊ฒŒ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์ธ๊ฐ€?

Suspense๋Š” React์—์„œ ๋ฐ์ดํ„ฐ ๋กœ๋”ฉ ์ƒํƒœ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๋„์ž…๋œ ๊ฐœ๋…์œผ๋กœ, ์ฃผ๋กœ ๋น„๋™๊ธฐ ์ž‘์—…๊ณผ ์—ฐ๊ด€๋˜์–ด ์žˆ๋‹ค.

Suspense์˜ ๋™์ž‘ ์›๋ฆฌ๋Š” Promise์˜ ์ƒํƒœ์™€ ๋ฐ€์ ‘ํ•˜๊ฒŒ ๊ด€๋ จ๋˜์–ด ์žˆ์œผ๋ฉฐ, ์ด๋ฅผ ํ†ตํ•ด ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ์†์‰ฝ๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

Pending ์ƒํƒœ (๋Œ€๊ธฐ ์ค‘):

  • ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋น„๋™๊ธฐ ์ž‘์—…์„ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ๋•Œ, ํ•ด๋‹น Promise๋Š” ์ฒ˜์Œ์— pending ์ƒํƒœ๊ฐ€ ๋œ๋‹ค.

  • ์ด ์‹œ์ ์—์„œ Suspense๋Š” ๋กœ๋”ฉ ์ƒํƒœ๋ฅผ ๊ฐ์ง€ํ•˜๊ณ , fallback์œผ๋กœ ์ง€์ •๋œ ๋กœ๋”ฉ UI๋ฅผ ํ‘œ์‹œํ•œ๋‹ค.

  • ์˜ˆ๋ฅผ ๋“ค์–ด, ๋„คํŠธ์›Œํฌ ์š”์ฒญ์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ์Šคํ”ผ๋„ˆ(spinner)๋‚˜ ๋กœ๋”ฉ ๋ฉ”์‹œ์ง€๊ฐ€ ํ‘œ์‹œ๋  ์ˆ˜ ์žˆ๋‹ค.

Fulfilled ์ƒํƒœ (์™„๋ฃŒ๋จ):

  • ๋น„๋™๊ธฐ ์ž‘์—…์ด ์„ฑ๊ณต์ ์œผ๋กœ ์™„๋ฃŒ๋˜๋ฉด Promise๋Š” fulfilled ์ƒํƒœ๊ฐ€ ๋œ๋‹ค.

  • ์ด ๋•Œ Suspense๋Š” ๋กœ๋”ฉ UI๋ฅผ ์ œ๊ฑฐํ•˜๊ณ , ๋ฐ์ดํ„ฐ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ๊ฐ€์ ธ์˜จ ์ปดํฌ๋„ŒํŠธ๋ฅผ ํ™”๋ฉด์— ๋ Œ๋”๋งํ•œ๋‹ค.

  • ์˜ˆ๋ฅผ ๋“ค์–ด, ์„œ๋ฒ„์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ๋ฐ›์•„์™€ ํ™”๋ฉด์— ๋ฐ์ดํ„ฐ๋ฅผ ํ‘œ์‹œํ•œ๋‹ค.

Rejected ์ƒํƒœ (์‹คํŒจํ•จ):

  • ๋น„๋™๊ธฐ ์ž‘์—…์ด ์‹คํŒจํ•˜๋ฉด Promise๋Š” rejected ์ƒํƒœ๊ฐ€ ๋œ๋‹ค.

  • ์ด ๊ฒฝ์šฐ, Suspense ์ž์ฒด๋Š” ์‹คํŒจ ์ƒํƒœ๋ฅผ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์ง€๋งŒ, ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์—์„œ ์—๋Ÿฌ ๊ฒฝ๊ณ„(Error Boundary)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์—๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์˜ˆ๋ฅผ ๋“ค์–ด, ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜์˜€์„ ๊ฒฝ์šฐ ์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋ฅผ ํ‘œ์‹œํ•œ๋‹ค.

ย 

Suspense ๋‚จ์šฉ์˜ ๋ฌธ์ œ

์•„๋ž˜ ์˜ˆ์‹œ์—์„œ๋Š” Before ์ปดํฌ๋„ŒํŠธ๋ฅผ Suspense๊ฐ€ ๊ฐ์‹ธ๊ณ  ์žˆ๋‹ค.
๊ทธ๋ฆฌ๊ณ  ๋‚ด๋ถ€์—์„œ 2๊ฐœ์˜ Query๋ฅผ ์š”์ฒญํ•˜๊ณ  ์žˆ๋‹ค.



// App.jsx
function App() {
  return (
    <Suspense fallback={<div>...loading</div>}>
      <Before />
    </Suspense>
  );
}

// Before.jsx
const BASE_URL = "https://jsonplaceholder.typicode.com";
const client = axios.create({ baseURL: BASE_URL });

function Before() {
  const { data: todoList } = useQuery("todos", () => client.get("/todos"), {
    suspense: true, // โœจ
  });

  const { data: postList } = useQuery("posts", () => client.get("/posts"), {
    suspense: true, // โœจ
  });

  return (
    <div style={{ display: "flex" }}>
      <section>
        <h2>Todo List</h2>
        {todoList?.data.map(({ id, title }) => (
          <div key={id}>{title}</div>
        ))}
      </section>
      <section>
        <h2>Post List</h2>
        {postList?.data.map(({ id, title }) => (
          <div key={id}>{title}</div>
        ))}
      </section>
    </div>
  );
}


Enter fullscreen mode Exit fullscreen mode

API ์š”์ฒญ์ด ์–ด๋–ป๊ฒŒ ๊ฐ€๊ณ  ์žˆ๋Š”์ง€ ๋„คํŠธ์›Œํฌ ํƒญ์„ ์‚ดํŽด๋ณด๋ฉด

Image description

network waterfall์„ ๋งŒ๋“ค๊ณ  ์žˆ๋‹ค. ํ•ด๋‹น ๋ฌธ์ œ์ ์„ ๊ฒช์œผ๋ฉด์„œ ์•ฑ์˜ ๋กœ๋”ฉ ์‹œ๊ฐ„์ด ๊ธธ์–ด์ง€๊ฒŒ ๋˜์—ˆ๋‹ค.

์™œ ์ด๋Ÿฐ ํ˜„์ƒ์ด ๋ฐœ์ƒํ•˜์˜€์„๊นŒ? ์›์ธ์€ ๋ฐ”๋กœ Suspense์˜ ์ž˜๋ชป๋œ ์‚ฌ์šฉ, ์•„๋‹ˆ ์ž˜ ๋ชจ๋ฅด๊ณ  ์‚ฌ์šฉํ•œ ์›์ธ์ด ๋” ํฌ๋‹ค.

์œ„์—์„œ ์„ค๋ช…ํ•œ ๋Œ€๋กœ Suspense๋Š” Promise ์ƒํƒœ์— ๋”ฐ๋ผ์„œ children ๋˜๋Š” fallback ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ฆ‰, pending ์ƒํƒœ์ผ ๋•Œ์—๋Š” Loading์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  ์žˆ๊ณ , children์„ ์‹คํ–‰์‹œํ‚ค์ง€ ์•Š๋Š”๋‹ค.

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์—, ํ•˜๋‚˜์˜ API ์š”์ฒญ์ด ๋ฐœ์ƒํ•˜๋ฉด children ์ปดํฌ๋„ŒํŠธ์˜ ์‹คํ–‰์€ ๋ฉˆ์ถ”๊ณ  fallback์„ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋œ๋‹ค. Promise๊ฐ€ fulfilled ์ƒํƒœ๊ฐ€ ๋˜๋ฉด ๋‹ค์‹œ children์„ ๋ฐ˜ํ™˜ํ•˜์—ฌ children ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•œ๋‹ค.

์ด๋Ÿฌํ•œ ์ด์œ  ๋•Œ๋ฌธ์— Suspense๊ฐ€ ๊ฐ์‹ธ๊ณ  ์žˆ๋Š” ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ์—์„œ 2๊ฐœ ์ด์ƒ์˜ ์š”์ฒญ์„ ํ•  ๋•Œ ๋„คํŠธ์›Œํฌ ๋ณ‘๋ชฉ ํ˜„์ƒ์ด ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค.

ย 

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• 1 - Component์™€ Suspense 1:1 ๋Œ€์‘

Suspense ๋‚ด์˜ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋‘ ๊ฐœ ์ด์ƒ์˜ ์š”์ฒญ์ด ๋ฐœ์ƒํ•˜๋ฉด ๋„คํŠธ์›Œํฌ water fall์ด ์ง๋ ฌ๋กœ ์ฒ˜๋ฆฌ๋˜๋Š” ํ˜„์ƒ์ด ์ƒ๊ธด๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ํ•œ ์ปดํฌ๋„ŒํŠธ์— ํ•˜๋‚˜์˜ ์š”์ฒญ์„ ์œ ์ง€ํ•˜๋ฉด ํ•ด๊ฒฐ๋œ๋‹ค.

โœจ ๋‘ ๊ฐœ ์š”์ฒญ ๋ชจ๋‘ useQuery, suspense: true ๋กœ ์š”์ฒญ ์‹œ

์•„๋ž˜ ์ฝ”๋“œ๋Š” 2๊ฐœ์˜ ์ปดํฌ๋„ŒํŠธ๋กœ ๋ถ„๋ฆฌํ•˜๊ณ , ๊ฐ๊ฐ Query ์š”์ฒญ์„ ์ˆ˜ํ–‰ํ•˜๊ณ , ๊ฐ๊ฐ Suspense๋กœ ๊ฐ์‹ธ์ค€ ์ฝ”๋“œ์ด๋‹ค.



function AfterEachSuspense() {
  return (
    <div>
      <div style={{ display: "flex" }}>
        <section>
          <h2>Todo List</h2>
          <Suspense fallback={<div>...loading</div>}>
            <TodoList />
          </Suspense>
        </section>
        <section>
          <h2>Post List</h2>
          <Suspense fallback={<div>...loading</div>}>
            <PostList />
          </Suspense>
        </section>
      </div>
    </div>
  );
}

const TodoList = () => {
  const { data: todoList } = useQuery("todos", () => client.get("/todos"), {
    suspense: true, // โœจ
  });

  return (
    <div>
      {todoList?.data.map(({ id, title }) => (
        <div key={id}>{title}</div>
      ))}
    </div>
  );
};

const PostList = () => {
  const { data: postList } = useQuery("posts", () => client.get("/posts"), {
    suspense: true, // โœจ
  });

  return (
    <div>
      {postList?.data.map(({ id, title }) => (
        <div key={id}>{title}</div>
      ))}
    </div>
  );
};


Enter fullscreen mode Exit fullscreen mode

๋„คํŠธ์›Œํฌ ์š”์ฒญ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

Image description

๋ณ‘๋ชฉ ํ˜„์ƒ์„ ํ•ด๊ฒฐํ•˜๊ณ  ์ •์ƒ์ ์œผ๋กœ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋˜๋Š” ๋ชจ์Šต์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

Suspense๊ฐ€ ๋ถ„๋ฆฌ๋˜์—ˆ๊ณ , ๊ฐ๊ฐ์˜ Suspense๊ฐ€ ๊ฐ๊ฐ์˜ children์„ ๊ด€์žฅํ•˜๋ฏ€๋กœ ๋ณ‘๋ ฌ์ ์œผ๋กœ ์‹คํ–‰๋˜๋Š” ๊ฒƒ์ด ๋‹น์—ฐํ•œ ๊ฒฐ๊ณผ๋‹ค.

ํ•˜์ง€๋งŒ ์ด ๋ฐฉ์‹์€ ์ƒํ™ฉ์— ๋”ฐ๋ผ์„œ ๋ฌธ์ œ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค.

๋ฐ”๋กœ, ๋กœ๋”ฉ ์ƒํƒœ๊ฐ€ ์ œ๊ฐ๊ฐ ์ด๋ผ๋Š” ๊ฒƒ์ด๋‹ค.

์œ„ ๋„คํŠธ์›Œํฌ ํƒญ์—์„œ todos์™€ posts ์š”์ฒญ์„ ๋ณด๋ฉด ๋๋‚˜๋Š” ์‹œ๊ฐ„์ด ๋‹ค๋ฅด๋ฉฐ, ๊ฐ๊ฐ์˜ Suspense ๋Š” ๊ฐ๊ฐ์˜ ๋„คํŠธ์›Œํฌ ์š”์ฒญ์ด ๋๋‚˜๋Š” ๊ฒƒ์„ ๊ฐ์ง€ํ•˜์—ฌ children์„ ๋ Œ๋”๋ง ํ•œ๋‹ค. ์ฆ‰, ์š”์ฒญ์ด ๋จผ์ € ๋๋‚œ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋จผ์ € ๋ณด์—ฌ์ง€๊ฒŒ ๋œ๋‹ค.

TodoList๊ฐ€ ๋จผ์ € ๋ Œ๋”๋ง ๋œ๋‹ค๋ฉด ์œ ์ €์—๊ฒŒ ๋ฒ„๋ฒ…๊ฑฐ๋ฆฌ๋Š” ๋Š๊น€์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์—์„œ ์œ ์ € ๊ฒฝํ—˜์„ ์•…ํ™”์‹œํ‚ฌ ๊ฐ€๋Šฅ์„ฑ๋„ ์žˆ๋‹ค. ์ด๋Š” ์ƒํ™ฉ์— ๋”ฐ๋ผ์„œ ์ข‹์€ ๊ฒฝํ—˜์ผ ์ˆ˜ ์žˆ๊ณ , ์ข‹์ง€ ์•Š์€ ๊ฒฝํ—˜์ผ ์ˆ˜๋„ ์žˆ๋‹ค.

์ •๋ฆฌํ•˜์ž๋ฉด, ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ถ„๋ฆฌํ•œ ํ›„, ๊ฐ๊ฐ Suspense๋ฅผ ๊ฐ์‹ธ์ฃผ๋Š” ๊ฒƒ์€ ์œ ์ € ๊ฒฝํ—˜์„ ์•…ํ™”์‹œํ‚ฌ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ๋‘ ์ปดํฌ๋„ŒํŠธ ๋ชจ๋‘ ๋กœ๋”ฉ์ด ๋๋‚˜๋Š” ์‹œ์ ์— ํ•œ๋ฒˆ์— ๋ Œ๋”๋ง ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๊ฒ ๋‹ค.

ย 

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• 2 - Component์™€ Suspense n:1 ๋Œ€์‘

์œ„์™€ ๊ฐ™์ด ์ปดํฌ๋„ŒํŠธ๋กœ Query๋ฅผ ๊ฐ์‹ธ์—ฌ ์š”์ฒญ์„ ๋ถ„๋ฆฌํ•˜์˜€์ง€๋งŒ, Suspense๋Š” ํ•˜๋‚˜๋กœ ๊ฐ์‹ธ๊ณ  ์žˆ๋Š” ์ ์ด ๋‹ค๋ฅด๋‹ค.



function AfterSameSuspense() {
  return (
    <div>
      <Suspense fallback={<div>...loading</div>}>
        <div style={{ display: "flex" }}>
          <section>
            <h2>Todo List</h2>
            <TodoList />
          </section>
          <section>
            <h2>Post List</h2>
            <PostList />
          </section>
        </div>
      </Suspense>
    </div>
  );
}


Enter fullscreen mode Exit fullscreen mode

๋„คํŠธ์›Œํฌ ์š”์ฒญ ๊ฒฐ๊ณผ๋Š” ๋™์ผํ•˜๊ฒŒ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๋˜๊ณ  ์žˆ์œผ๋ฉฐ, ์ž„์˜์˜ API call์ด ๋จผ์ € ๋๋‚˜๋Š” ์ƒํ™ฉ์ด๋‹ค.

Image description

์˜๋„ํ•œ ๋Œ€๋กœ, ๋‘ ์š”์ฒญ์ด ๋ชจ๋‘ ๋๋‚  ๋•Œ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ๋ Œ๋”๋ง์ด ์ˆ˜ํ–‰๋œ๋‹ค.

์ด๋Š” Suspense ๋‚ด๋ถ€ ์ฝ”๋“œ๋ฅผ ์‚ดํŽด๋ด์•ผ ์ •ํ™•ํžˆ ์•Œ๊ฒ ์ง€๋งŒ, Suspense ๋‚ด๋ถ€์—์„œ API ์š”์ฒญ์ด ๋ฐœ์ƒํ•œ ์†Œ์žฌ๋ฅผ ํŒŒ์•…ํ•˜์—ฌ, ๊ทธ๊ณณ์€ fallback์œผ๋กœ ๋Œ€์ฒดํ•˜๊ณ , ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์€ ์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰์‹œํ‚ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

ย 

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• 3 - useQueries

์—ฌ๋Ÿฌ ๊ฐœ์˜ query๋ฅผ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰์‹œํ‚ฌ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” useQueries๋Š” Suspense์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ ์‹œ ์ •์ƒ์ ์œผ๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š๋Š” ์ด์Šˆ๊ฐ€ ์žˆ๋Š”๋ฐ v4.5.0 ํŒจ์น˜์— ํ•ด๋‹น ์‚ฌํ•ญ์ด ์ˆ˜์ •๋˜์—ˆ๋‹ค.



const results =   useQueries({queries: [
  {queryKey: ["posts"], queryFn: () => fetch("/posts") , suspense: true},
  {queryKey: ["comments"], queryFn: () => fetch("/comments"), suspense:true},
  {queryKey: ["issues"], queryFn: () => fetch("/issues"), suspense:true }
]})


Enter fullscreen mode Exit fullscreen mode

useQueries๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€ context๋ฅผ ์ด์šฉํ•ด ๋ณ‘๋ ฌ์ ์œผ๋กœ api๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์–ด์„œ context ์‚ฌ์šฉ์„ ์œ„ํ•œ ๋ถ€๊ฐ€์ ์ธ ๊ตฌํ˜„์„ ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.

ย 

๋งˆ์น˜๋ฉฐ

๊ฐ€๋…์„ฑ๊ณผ ํด๋ฆฐ ์ฝ”๋“œ๋„ ์ข‹์ง€๋งŒ ๋ฌด๋ถ„๋ณ„ํ•œ Suspense๋ฅผ ์‚ฌ์šฉ์œผ๋กœ ๋กœ๋”ฉ ์„ฑ๋Šฅ์„ ์ €ํ•˜ ์‹œํ‚ค๋Š” ๊ฒฐ๊ณผ๋ฅผ ๋‚˜์„ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ ‡๋“ฏ Suspense์˜ ์žฅ์ ๋งŒ ์ธ์ง€ํ•˜๊ณ  Suspense๋ฅผ ์‚ฌ์šฉํ•ด์„œ๋Š” ์•ˆ ๋˜๋ฉฐ, ๋™์ž‘ ์›๋ฆฌ์™€ ์ ์ ˆํ•œ poc๋ฅผ ํ†ตํ•ด ๊ณ ๋ฏผํ•ด ๋ณด์•„์•ผ ํ•œ๋‹ค.

reactquery Article's
30 articles in total
Favicon
Create an SSR Application with Vite, React, React Query and React Router
Favicon
TanStack query or RTK query.
Favicon
Simplified State Management with useRQState: A Better Alternative to useState
Favicon
Master React API Management with TanStack React Query: Best Practices & Examples
Favicon
How to Fetch Data Using Axios and React Query in ReactJS
Favicon
Efficient Refresh Token Implementation with React Query and Axios
Favicon
react-query swrjs alova In-Depth Comparison
Favicon
Mastering React Query. Simplifying Data Management in React with Separation Patterns
Favicon
Mastering React Query. Structuring Your Code for Scalability and Reusability
Favicon
Why you should try React Query?
Favicon
How to used Suspense?
Favicon
Infinite list loading ๐Ÿค”, with React Query - useInfiniteQuery hook !
Favicon
Building a CRUD app with React Query, TypeScript, and Axios
Favicon
TLDR; Suspense in react-query
Favicon
TLDR; gcTime & staleTime in react-query
Favicon
Building Infinite Scrolling in React Js with React Query v5
Favicon
Optimized Infinite Scroll with Next.js 14 Server Actions and React Query
Favicon
Building a Todo List with TypeScript and React Query: A Comprehensive Guide
Favicon
React Safe Query - A lightweight, type-safe wrapper built around React Query
Favicon
React Query Mutations Offline React-Native
Favicon
Improving UX by using cache
Favicon
How to organize your API layer in React using React Query
Favicon
Conociendo a React Query
Favicon
Build a CRUD App in React with Tanstack Query and Material UI [Final]
Favicon
Build a CRUD App in React with Tanstack Query and Material UI [Part 2]
Favicon
Integrating React Query with Next.js ๐Ÿš€
Favicon
Build a CRUD App in React with Tanstack Query and Material UI [Part 1]
Favicon
React query for data streaming
Favicon
Manual Fetch with Tanstack Query
Favicon
Setting up React Query in your Reactย project

Featured ones: