use - This feature is available in the latest Canary

Canary

use Hook์€ ํ˜„์žฌ React์˜ Canary ์ฑ„๋„๊ณผ ์‹คํ—˜ ์ฑ„๋„์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ React ๋ฆด๋ฆฌ์ฆˆ ์ฑ„๋„์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

use๋Š” Promise๋‚˜ context์™€ ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐธ์กฐํ•˜๋Š” React Hook์ž…๋‹ˆ๋‹ค.

const value = use(resource);

Reference

use(resource)

์ปดํฌ๋„ŒํŠธ์—์„œ Promise๋‚˜ context์™€ ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฐธ์กฐํ•˜๋ ค๋ฉด use๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

import { use } from 'react';

function MessageComponent({ messagePromise }) {
const message = use(messagePromise);
const theme = use(ThemeContext);
// ...

๋‹ค๋ฅธ React Hook๊ณผ ๋‹ฌ๋ฆฌ use๋Š” if์™€ ๊ฐ™์€ ์กฐ๊ฑด๋ฌธ๊ณผ ๋ฐ˜๋ณต๋ฌธ ๋‚ด๋ถ€์—์„œ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ React Hook๊ณผ ๊ฐ™์ด use๋Š” ์ปดํฌ๋„ŒํŠธ ๋˜๋Š” Hook์—์„œ๋งŒ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Promise์™€ ํ•จ๊ป˜ ํ˜ธ์ถœ๋  ๋•Œ use Hook์€ Suspense ๋ฐ error boundary์™€ ํ†ตํ•ฉ๋ฉ๋‹ˆ๋‹ค. use์— ์ „๋‹ฌ๋œ Promise๊ฐ€ ๋ณด๋ฅ˜๋˜๋Š” ๋™์•ˆ use๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋Š” ์ผ์‹œ ์ค‘๋‹จ๋ฉ๋‹ˆ๋‹ค. use๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๊ฐ€ Suspense ๊ฒฝ๊ณ„๋กœ ๋‘˜๋Ÿฌ์‹ธ์—ฌ ์žˆ์œผ๋ฉด fallback์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. Promise๊ฐ€ ๋ฆฌ์กธ๋ธŒ๋˜๋ฉด Suspense fallback์€ use Hook์ด ๋ฐ˜ํ™˜ํ•œ ์ปดํฌ๋„ŒํŠธ๋กœ ๋Œ€์ฒด๋ฉ๋‹ˆ๋‹ค. use์— ์ „๋‹ฌ๋œ Promise๊ฐ€ ๊ฑฐ๋ถ€๋˜๋ฉด ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด Error Boundary์˜ fallback์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

์‚ฌ์šฉ๋ฒ• ํ™•์ธํ•˜๊ธฐ

๋งค๊ฐœ๋ณ€์ˆ˜

  • resource: ์ฐธ์กฐํ•˜๋ ค๋Š” ๋ฐ์ดํ„ฐ์ž…๋‹ˆ๋‹ค. ๋ฐ์ดํ„ฐ๋Š” Promise๋‚˜ context์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ˜ํ™˜๊ฐ’

use Hook์€ Promise๋‚˜ context์—์„œ ์ฐธ์กฐํ•œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

์ฃผ์˜ ์‚ฌํ•ญ

  • use Hook์€ ์ปดํฌ๋„ŒํŠธ๋‚˜ Hook ๋‚ด๋ถ€์—์„œ ํ˜ธ์ถœ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ fetch ํ•  ๋•Œ๋Š” use๋ณด๋‹ค async ๋ฐ await๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
  • async ๋ฐ await์€ await์ด ํ˜ธ์ถœ๋œ ์‹œ์ ๋ถ€ํ„ฐ ๋ Œ๋”๋ง์„ ์‹œ์ž‘ํ•˜๋Š” ๋ฐ˜๋ฉด use๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๋ฆฌ์กธ๋ธŒ๋œ ํ›„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฆฌ๋ Œ๋”๋งํ•ฉ๋‹ˆ๋‹ค.
  • ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์—์„œ Promise๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์—์„œ Promise๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์— ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์—์„œ ์ƒ์„ฑ๋œ Promise๋Š” ๋ Œ๋”๋งํ•  ๋•Œ๋งˆ๋‹ค ๋‹ค์‹œ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์—์„œ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋กœ ์ „๋‹ฌ๋œ Promise๋Š” ๋ฆฌ๋ Œ๋”๋ง ์ „๋ฐ˜์— ๊ฑธ์ณ ์•ˆ์ •์ ์ž…๋‹ˆ๋‹ค. ์˜ˆ์‹œ ํ™•์ธํ•˜๊ธฐ.

์‚ฌ์šฉ๋ฒ•

use๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ context ์ฐธ์กฐํ•˜๊ธฐ

context๊ฐ€ use์— ์ „๋‹ฌ๋˜๋ฉด useContext์™€ ์œ ์‚ฌํ•˜๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. useContext๋Š” ์ปดํฌ๋„ŒํŠธ์˜ ์ตœ์ƒ์œ„ ์ˆ˜์ค€์—์„œ ํ˜ธ์ถœํ•ด์•ผ ํ•˜์ง€๋งŒ use๋Š” if์™€ ๊ฐ™์€ ์กฐ๊ฑด๋ฌธ์ด๋‚˜ for๊ณผ ๊ฐ™์€ ๋ฐ˜๋ณต๋ฌธ ๋‚ด๋ถ€์—์„œ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. use๋Š” ์œ ์—ฐํ•˜๋ฏ€๋กœ useContext๋ณด๋‹ค ์„ ํ˜ธ๋ฉ๋‹ˆ๋‹ค.

import { use } from 'react';

function Button() {
const theme = use(ThemeContext);
// ...

use๋Š” ์ „๋‹ฌํ•œ context์˜ context ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. context ๊ฐ’์„ ๊ฒฐ์ •ํ•˜๊ธฐ ์œ„ํ•ด React๋Š” ์ปดํฌ๋„ŒํŠธ ํŠธ๋ฆฌ๋ฅผ ๊ฒ€์ƒ‰ํ•˜๊ณ  ์œ„์—์„œ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด context provider๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค.

context๋ฅผ Button์— ์ „๋‹ฌํ•˜๋ ค๋ฉด Button ๋˜๋Š” ์ƒ์œ„ ์ปดํฌ๋„ŒํŠธ ์ค‘ ํ•˜๋‚˜๋ฅผ context provider๋กœ ๋ž˜ํ•‘ํ•ฉ๋‹ˆ๋‹ค.

function MyPage() {
return (
<ThemeContext.Provider value="dark">
<Form />
</ThemeContext.Provider>
);
}

function Form() {
// ... ๋ฒ„ํŠผ ๋ Œ๋”๋ง ...
}

provider์™€ Button ์‚ฌ์ด์— ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์žˆ๋Š”์ง€๋Š” ์ค‘์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. Form ๋‚ด๋ถ€์˜ ์–ด๋Š ๊ณณ์ด๋“  Button์ด use(ThemeContext)๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด "dark"๋ฅผ ๊ฐ’์œผ๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค

useContext์™€ ๋‹ฌ๋ฆฌ use๋Š” if์™€ ๊ฐ™์€ ์กฐ๊ฑด๋ฌธ๊ณผ ๋ฐ˜๋ณต๋ฌธ ๋‚ด๋ถ€์—์„œ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

function HorizontalRule({ show }) {
if (show) {
const theme = use(ThemeContext);
return <hr className={theme} />;
}
return false;
}

use๋Š” if ๋‚ด๋ถ€์—์„œ ํ˜ธ์ถœ๋˜๋ฏ€๋กœ context์—์„œ ์กฐ๊ฑด๋ถ€๋กœ ๊ฐ’์„ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์˜ํ•˜์„ธ์š”!

useContext์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ use(context)๋Š” ํ˜ธ์ถœ ์ปดํฌ๋„ŒํŠธ์˜ ์œ„์—์„œ ๊ฐ€์žฅ ๊ฐ€๊นŒ์šด context provider๋ฅผ ์ฐพ์Šต๋‹ˆ๋‹ค. ์œ„์ชฝ์œผ๋กœ ๊ฒ€์ƒ‰ํ•˜๋ฉฐ use(context)๋ฅผ ํ˜ธ์ถœ ์ปดํฌ๋„ŒํŠธ ๋‚ด๋ถ€์˜ context provider๋Š” ๊ณ ๋ คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

import { createContext, use } from 'react';

const ThemeContext = createContext(null);

export default function MyApp() {
  return (
    <ThemeContext.Provider value="dark">
      <Form />
    </ThemeContext.Provider>
  )
}

function Form() {
  return (
    <Panel title="Welcome">
      <Button show={true}>Sign up</Button>
      <Button show={false}>Log in</Button>
    </Panel>
  );
}

function Panel({ title, children }) {
  const theme = use(ThemeContext);
  const className = 'panel-' + theme;
  return (
    <section className={className}>
      <h1>{title}</h1>
      {children}
    </section>
  )
}

function Button({ show, children }) {
  if (show) {
    const theme = use(ThemeContext);
    const className = 'button-' + theme;
    return (
      <button className={className}>
        {children}
      </button>
    );
  }
  return false
}

์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ฐ์ดํ„ฐ ์ŠคํŠธ๋ฆฌ๋ฐํ•˜๊ธฐ

์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์—์„œ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋กœ Promise prop์„ ์ „๋‹ฌํ•˜์—ฌ ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ŠคํŠธ๋ฆฌ๋ฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import { fetchMessage } from './lib.js';
import { Message } from './message.js';

export default function App() {
const messagePromise = fetchMessage();
return (
<Suspense fallback={<p>waiting for message...</p>}>
<Message messagePromise={messagePromise} />
</Suspense>
);
}

ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋Š” prop์œผ๋กœ ๋ฐ›์€ Promise๋ฅผ use Hook์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค. Client Component๋Š” ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ๊ฐ€ ์ฒ˜์Œ์— ์ƒ์„ฑํ•œ Promise์—์„œ ๊ฐ’์„ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// message.js
'use client';

import { use } from 'react';

export function Message({ messagePromise }) {
const messageContent = use(messagePromise);
return <p>Here is the message: {messageContent}</p>;
}

Message๋Š” Suspense๋กœ ๋ž˜ํ•‘๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ Promise๊ฐ€ ๋ฆฌ์กธ๋ธŒ๋  ๋•Œ๊นŒ์ง€ fallback์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. Promise๊ฐ€ ๋ฆฌ์กธ๋ธŒ๋˜๋ฉด use Hook์ด ๊ฐ’์„ ์ฐธ์กฐํ•˜๊ณ  Message ์ปดํฌ๋„ŒํŠธ๊ฐ€ Suspense fallback์„ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค.

"use client";

import { use, Suspense } from "react";

function Message({ messagePromise }) {
  const messageContent = use(messagePromise);
  return <p>Here is the message: {messageContent}</p>;
}

export function MessageContainer({ messagePromise }) {
  return (
    <Suspense fallback={<p>โŒ›Downloading message...</p>}>
      <Message messagePromise={messagePromise} />
    </Suspense>
  );
}

์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค!

์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์—์„œ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋กœ Promise๋ฅผ ์ „๋‹ฌํ•  ๋•Œ ๋ฆฌ์กธ๋ธŒ๋œ ๊ฐ’์ด ์ง๋ ฌํ™” ๊ฐ€๋Šฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•จ์ˆ˜๋Š” ์ง๋ ฌํ™”ํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ Promise์˜ ๋ฆฌ์กธ๋ธŒ ๊ฐ’์ด ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

Deep Dive

์„œ๋ฒ„ ๋˜๋Š” ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์—์„œ ํ”„๋กœ๋ฏธ์Šค๋ฅผ ๋ฆฌ์กธ๋ธŒํ•ด๋งŒ ํ•˜๋‚˜์š”?

Promise๋Š” ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์—์„œ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋กœ ์ „๋‹ฌ๋  ์ˆ˜ ์žˆ์œผ๋ฉฐ use Hook์„ ํ†ตํ•ด ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์—์„œ ๋ฆฌ์กธ๋ธŒ๋ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์—์„œ await์„ ์‚ฌ์šฉํ•˜์—ฌ Promise๋ฅผ ๋ฆฌ์กธ๋ธŒํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ์— prop์œผ๋กœ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

export default function App() {
const messageContent = await fetchMessage();
return <Message messageContent={messageContent} />
}

ํ•˜์ง€๋งŒ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์—์„œ await์„ ์‚ฌ์šฉํ•˜๋ฉด await ๋ฌธ์ด ์™„๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๋ Œ๋”๋ง์ด ์ฐจ๋‹จ๋ฉ๋‹ˆ๋‹ค. ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์—์„œ ํด๋ผ์ด์–ธํŠธ ์ปดํฌ๋„ŒํŠธ๋กœ Promise๋ฅผ prop์œผ๋กœ ์ „๋‹ฌํ•˜๋ฉด Promise๊ฐ€ ์„œ๋ฒ„ ์ปดํฌ๋„ŒํŠธ์˜ ๋ Œ๋”๋ง์„ ์ฐจ๋‹จํ•˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฑฐ๋ถ€๋œ Promise ์ฒ˜๋ฆฌํ•˜๊ธฐ

๊ฒฝ์šฐ์— ๋”ฐ๋ผ use์— ์ „๋‹ฌ๋œ Promise๊ฐ€ ๊ฑฐ๋ถ€๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฑฐ๋ถ€๋œ ํ”„๋กœ๋ฏธ์Šค๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์€ 2๊ฐ€์ง€๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

  1. error boundary๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์˜ค๋ฅ˜๋ฅผ ํ‘œ์‹œํ•˜๊ธฐ
  2. Promise.catch๋กœ ๋Œ€์ฒด ๊ฐ’ ์ œ๊ณตํ•˜๊ธฐ

์ฃผ์˜ํ•˜์„ธ์š”!

use๋Š” try-catch ๋ธ”๋ก์—์„œ ํ˜ธ์ถœํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. try-catch ๋ธ”๋ก ๋Œ€์‹  ์ปดํฌ๋„ŒํŠธ๋ฅผ Error Boundary๋กœ ๋ž˜ํ•‘ํ•˜๊ฑฐ๋‚˜ Promise์˜ catch ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋Œ€์ฒด ๊ฐ’์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

error boudary๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์˜ค๋ฅ˜ ํ‘œ์‹œํ•˜๊ธฐ

Promise๊ฐ€ ๊ฑฐ๋ถ€๋  ๋•Œ ์˜ค๋ฅ˜๋ฅผ ํ‘œ์‹œํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด error boundary๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. error boundary๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด use Hook์„ ํ˜ธ์ถœํ•˜๋Š” ์ปดํฌ๋„ŒํŠธ๋ฅผ error boundary๋กœ ๋ž˜ํ•‘ํ•ฉ๋‹ˆ๋‹ค. use์— ์ „๋‹ฌ๋œ Promise๊ฐ€ ๊ฑฐ๋ถ€๋˜๋ฉด error boundary์— ๋Œ€ํ•œ fallback์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

"use client";

import { use, Suspense } from "react";
import { ErrorBoundary } from "react-error-boundary";

export function MessageContainer({ messagePromise }) {
  return (
    <ErrorBoundary fallback={<p>โš ๏ธSomething went wrong</p>}>
      <Suspense fallback={<p>โŒ›Downloading message...</p>}>
        <Message messagePromise={messagePromise} />
      </Suspense>
    </ErrorBoundary>
  );
}

function Message({ messagePromise }) {
  const content = use(messagePromise);
  return <p>Here is the message: {content}</p>;
}

Promise.catch๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋Œ€์ฒด ๊ฐ’ ์ œ๊ณตํ•˜๊ธฐ

use์— ์ „๋‹ฌ๋œ Promise๊ฐ€ ๊ฑฐ๋ถ€๋  ๋•Œ ๋Œ€์ฒด ๊ฐ’์„ ์ œ๊ณตํ•˜๋ ค๋ฉด Promise์˜ catch๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

import { Message } from './message.js';

export default function App() {
const messagePromise = new Promise((resolve, reject) => {
reject();
}).catch(() => {
return "no new message found.";
});

return (
<Suspense fallback={<p>waiting for message...</p>}>
<Message messagePromise={messagePromise} />
</Suspense>
);
}

Promise์˜ catch ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด Promise ๊ฐ์ฒด์—์„œ catch๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. catch๋Š” ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€๋ฅผ ์ธ์ž๋กœ ๋ฐ›๋Š” ํ•จ์ˆ˜๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์Šต๋‹ˆ๋‹ค. catch์— ์ „๋‹ฌ๋œ ํ•จ์ˆ˜๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š”ํ•˜๋Š” ๊ฐ’์€ ๋ชจ๋‘ Promise์˜ ๋ฆฌ์กธ๋ธŒ ๊ฐ’์œผ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.


ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…

โ€œSuspense Exception: This is not a real error!โ€

React ์ปดํฌ๋„ŒํŠธ ๋˜๋Š” hook ํ•จ์ˆ˜ ์™ธ๋ถ€์—์„œ, ํ˜น์€ try-catch ๋ธ”๋ก์—์„œ use๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์žˆ๋Š” ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค. try-catch ๋ธ”๋ก ๋‚ด์—์„œ use๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ ์ปดํฌ๋„ŒํŠธ๋ฅผ error boundary๋กœ ๋ž˜ํ•‘ํ•˜๊ฑฐ๋‚˜ Promise์˜ catch๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์—๋Ÿฌ๋ฅผ ๋ฐœ๊ฒฌํ•˜๊ณ  Promise๋ฅผ ๋‹ค๋ฅธ ๊ฐ’์œผ๋กœ ๋ฆฌ์กธ๋ธŒํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ์‹œ ํ™•์ธํ•˜๊ธฐ

React ์ปดํฌ๋„ŒํŠธ๋‚˜ Hook ํ•จ์ˆ˜ ์™ธ๋ถ€์—์„œ use๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒฝ์šฐ use ํ˜ธ์ถœ์„ React ์ปดํฌ๋„ŒํŠธ๋‚˜ Hook ํ•จ์ˆ˜๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.

function MessageComponent({messagePromise}) {
function download() {
// โŒ `use`๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ํ•จ์ˆ˜๊ฐ€ ์ปดํฌ๋„ŒํŠธ๋‚˜ hook์ด ์•„๋‹™๋‹ˆ๋‹ค.
const message = use(messagePromise);
// ...

์ปดํฌ๋„ŒํŠธ ํด๋กœ์ € ์™ธ๋ถ€์—์„œ use๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ use๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ํ•จ์ˆ˜๋Š” ์ปดํฌ๋„ŒํŠธ ๋˜๋Š” Hook์ž…๋‹ˆ๋‹ค.

function MessageComponent({messagePromise}) {
// โœ… `use`๊ฐ€ ์ปดํฌ๋„ŒํŠธ์—์„œ ํ˜ธ์ถœ๋˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
const message = use(messagePromise);
// ...