use γ―γγγγΉ (Promise) γγ³γ³γγ―γΉγγͺγ©οΏ½?γͺγ½γΌγΉγγε€γθͺγΏεγγγοΏ½? React γγγ―γ§γγ
const value = use(resource);γͺγγ‘γ¬γ³γΉ
use(resource)
γ³γ³γγΌγγ³γε
γ§ use γεΌγ³εΊγγγγγγΉγγ³γ³γγ―γΉγγͺγ©οΏ½?γͺγ½γΌγΉγγε€γθͺγΏεγγΎγγ
import { use } from 'react';
function MessageComponent({ messagePromise }) {
const message = use(messagePromise);
const theme = use(ThemeContext);
// ...δ»οΏ½?γγγγ React γγγ―γ¨γ―η°γͺγγuse γ― if οΏ½?γγγͺγ«γΌγγζ‘δ»Άζε
γ§γεΌγ³εΊγγγ¨γγ§γγΎγγδ»οΏ½? React γγγ―γ¨εζ§γ«γuse γεΌγ³εΊγι’ζ°γ―γ³γ³γγΌγγ³γγΎγγ―γγγ―γ§γͺγγγ°γͺγγΎγγγ
γγγγΉγεΌζ°γ«γγ¦εΌγ³εΊγγε ΄εγuse γγγ―γ― Suspense γγ¨γ©γΌγγ¦γ³γγͺ (error boundary) γ¨εθͺΏγγ¦εδ½γγΎγγuse γεΌγ³εΊγγ³γ³γγΌγγ³γγ―γuse γ«ζΈ‘γγγγγγγΉγδΏηδΈ (pending) γ§γγιγγ΅γΉγγ³γ (suspend) γγΎγγuse γεΌγ³εΊγγ³γ³γγΌγγ³γγγ΅γΉγγ³γΉγγ¦γ³γγͺγ§γ©γγγγγ¦γγε ΄εγγγ©γΌγ«γγγ―γ葨瀺γγγΎγγγγγγΉγθ§£ζ±Ί (resolve) γγγζηΉγ§γγ΅γΉγγ³γΉγγ©γΌγ«γγγ―γ―γuse γγγ―γγθΏγγγγγΌγΏγδ½Ώη¨γγ¦γ¬γ³γγΌγγγγ³γ³γγΌγγ³γοΏ½?ε
οΏ½?οΏ½γ«οΏ½?γζγγγΎγγuse γ«ζΈ‘γγγγγγγΉγζε¦ (reject) γγγγ¨γζγθΏγγ¨γ©γΌγγ¦γ³γγͺοΏ½?γγ©γΌγ«γγγ―γ葨瀺γγγΎγγ
εΌζ°
resource: ε€γθͺγΏεγγγγγΌγΏγ½γΌγΉγγͺγ½γΌγΉγ―γγγγΉγΎγγ― γ³γ³γγ―γΉγοΏ½?γγγγγ«γͺγγΎγγ
θΏγε€
use γγγ―γ―γγγγγΉοΏ½?θ§£ζ±Ίγγγε€γγ³γ³γγ―γΉγγͺγ©γγͺγ½γΌγΉγγθͺγΏεγ£γε€γθΏγγΎγγ
注ζηΉ
useγγγ―γ―γγ³γ³γγΌγγ³γγΎγγ―δ»οΏ½?γγγ―ε γ§εΌγ³εΊγεΏ θ¦γγγγΎγγ- γ΅γΌγγ³γ³γγΌγγ³γγ§γγΌγΏγγγ§γγγγιγ―γ
useγγγasyncγ¨awaitγεͺε γγ¦δ½Ώη¨γγ¦γγ γγγasyncγ¨awaitγ―awaitγεΌγ³εΊγγγε°ηΉγγγ¬γ³γγΌγειγγΎγγγuseγ―γγΌγΏγθ§£ζ±ΊγγεΎγ«γ³γ³γγΌγγ³γγζεγγγ¬γ³γγΌγγΎγγ - γ―γ©γ€γ’γ³γγ³γ³γγΌγγ³γγ§γγγγΉγδ½ζγγγγγγγ΅γΌγγ³γ³γγΌγγ³γγ§γγγγΉγδ½ζγγ¦γγγγ―γ©γ€γ’γ³γγ³γ³γγΌγγ³γγ«ζΈ‘γγγγ«γγ¦γγ γγγγ―γ©γ€γ’γ³γγ³γ³γγΌγγ³γγ§δ½ζγγγγγγγΉγ―γγ¬γ³γγΌγγ¨γ«εδ½ζγγγΎγγγ΅γΌγγ³γ³γγΌγγ³γγγγ―γ©γ€γ’γ³γγ³γ³γγΌγγ³γγ«ζΈ‘γγγγγγγΉγ―γεγ¬γ³γγΌιγ§δΈε€γ§γγγγ‘γοΏ½?δΎγεη §γγ¦γγ γγγ
δ½Ώη¨ζ³
use γ§γ³γ³γγ―γΉγγθͺγΏεγ
γ³γ³γγ―γΉγγ use γ«ζΈ‘γγγε ΄εγuseContext γ¨εζ§γ«εδ½γγΎγγuseContext γ―γ³γ³γγΌγγ³γοΏ½?γγγγ¬γγ«γ§εΌγ³εΊγεΏ
θ¦γγγγΎγγγuse γ― if γ for γͺγ©οΏ½?ζ‘δ»ΆεΌοΏ½?δΈγ§γεΌγ³εΊγγγ¨γγ§γγΎγγuse γ―γγζθ»γ§γγγγγuseContext γγγεͺε
ηγ«δ½Ώη¨γγ¦γγ γγγ
import { use } from 'react';
function Button() {
const theme = use(ThemeContext);
// ...use γ―γζΈ‘γγγ³γ³γγ―γΉγοΏ½?ε€γθΏγγΎγγγ³γ³γγ―γΉγοΏ½?ε€γζ±ΊοΏ½?οΏ½γγγγγ«γReact γ―γ³γ³γγΌγγ³γγγͺγΌγδΈζΉεγ«ζ€η΄’γγε½θ©²γ³γ³γγ―γΉγγ«ε―ΎεΏγγζγθΏγγ³γ³γγ―γΉγγγγγ€γ (context provider) γθ¦γ€γγΎγγ
Button γ«γ³γ³γγ―γΉγγζΈ‘γγ«γ―γγγγΎγγ―γοΏ½?θ¦ͺγ³γ³γγΌγγ³γοΏ½?γγγγγγε―ΎεΏγγγ³γ³γγ―γΉγγγγγ€γγ§γ©γγγγΎγγ
function MyPage() {
return (
<ThemeContext.Provider value="dark">
<Form />
</ThemeContext.Provider>
);
}
function Form() {
// ... renders buttons inside ...
}γγγγ€γγ¨ 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 ζοΏ½?δΈγγεΌγ³εΊγγ¦γγγγγζ‘δ»Άδ»γγ§γ³γ³γγ―γΉγγγε€γθͺγΏεγγγ¨γγ§γγΎγγ
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 }
γ΅γΌγγγγ―γ©γ€γ’γ³γγΈοΏ½?γγΌγΏγΉγγͺγΌγγ³γ°
γ΅γΌγγ³γ³γγΌγγ³γγγγ―γ©γ€γ’γ³γγ³γ³γγΌγγ³γ γ« props γ¨γγ¦γγγγΉγζΈ‘γγγ¨γ§γγ΅γΌγγγγ―γ©γ€γ’γ³γγ«γγΌγΏγγΉγγͺγΌγγ³γ°γγγγ¨γγ§γγΎγγ
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>
);
}γ―γ©γ€γ’γ³γγ³γ³γγΌγγ³γ γ―γεγεγ£γγγγγΉ γ use γγγ―γ«ζΈ‘γγΎγγγγγ«γγγ―γ©γ€γ’γ³γγ³γ³γγΌγγ³γγ―γγ΅γΌγγ³γ³γγΌγγ³γγζεγ«δ½ζγγγγγγΉγγε€γθͺγΏεγγγ¨γγ§γγΎγγ
// 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 γ§γ©γγγγγ¦γγγγγγγγγΉγθ§£ζ±ΊγγγγΎγ§γγ©γΌγ«γγγ―γ葨瀺γγγΎγγγγγγΉγθ§£ζ±Ίγγγγ¨γγοΏ½?ε€γ use γγγ―γ«γγ£γ¦θͺγΏεγγγMessage γ³γ³γγΌγγ³γγγ΅γΉγγ³γΉγγ©γΌγ«γγγ―γοΏ½?γζγγΎγγ
"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> ); }
γγγ«ζ·±γη₯γ
γγγγΉγ―γ΅γΌγγ³γ³γγΌγγ³γγγγ―γ©γ€γ’γ³γγ³γ³γγΌγγ³γγ«ζΈ‘γγuse γγγ―γδ½Ώγ£γ¦γ―γ©γ€γ’γ³γγ³γ³γγΌγγ³γγ§θ§£ζ±Ίγγγγ¨γγ§γγΎγγγΎγγawait γδ½Ώγ£γ¦γ΅γΌγγ³γ³γγΌγγ³γε΄γ§γγγγΉγθ§£ζ±ΊγγεΏ
θ¦γͺγγΌγΏγ props γ¨γγ¦γ―γ©γ€γ’γ³γγ³γ³γγΌγγ³γγ«ζΈ‘γγγ¨γε―θ½γ§γγγγ
export default function App() {
const messageContent = await fetchMessage();
return <Message messageContent={messageContent} />
}γγγγ΅γΌγγ³γ³γγΌγγ³γγ§ await γδ½Ώη¨γγγ¨γawait ζγη΅δΊγγγΎγ§γοΏ½?γ¬γ³γγΌγγγγγ―γγγΎγγγ΅γΌγγ³γ³γγΌγγ³γγγγ―γ©γ€γ’γ³γγ³γ³γγΌγγ³γγ«γγγγΉγζΈ‘γγγ¨γ§γγγγγΉγγ΅γΌγγ³γ³γγΌγγ³γοΏ½?γ¬γ³γγΌγγγγγ―γγγγ¨γι²γγγ¨γγ§γγΎγγ
ζε¦γγγγγγγΉοΏ½?εγζ±γ
ε ΄εγ«γγ£γ¦γ―γuse γ«ζΈ‘γγγγγγγΉγζε¦γγγγγ¨γγγγΎγγγγγγΉγζε¦γγγε ΄εγ«γγγε¦ηγγζΉζ³γ―δ»₯δΈοΏ½? 2 γ€γ§γγ
- γ¨γ©γΌγγ¦γ³γγͺγδ½Ώγ£γ¦γ¦γΌγΆγ«γ¨γ©γΌγ葨瀺γγ
Promise.catchγ§δ»£ζΏε€γζδΎγγ
γ¨γ©γΌγγ¦γ³γγͺγδ½Ώγ£γ¦γ¦γΌγΆγ«γ¨γ©γΌγ葨瀺γγ
γγγγΉγζε¦γγγγ¨γγ«γ¦γΌγΆγ«γ¨γ©γΌγ葨瀺γγγε ΄εγ―γγ¨γ©γΌγγ¦γ³γγͺ γδ½Ώη¨γ§γγΎγγγ¨γ©γΌγγ¦γ³γγͺγδ½Ώη¨γγγ«γ―γuse γγγ―γεΌγ³εΊγγ¦γγγ³γ³γγΌγγ³γγγ¨γ©γΌγγ¦γ³γγͺγ§γ©γγγγΎγγuse γ«ζΈ‘γγγγγγγΉγζε¦γγγγ¨γγ¨γ©γΌγγ¦γ³γγͺγ«ζΈγγγγγ©γΌγ«γγγ―γ葨瀺γγγΎγγ
"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 γ«ζΈ‘γγγγγγγΉγζε¦γγγγ¨γγ«δ»£ζΏε€γζδΎγγγε ΄εγγγγγΉοΏ½? 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>
);
}γγγγΉοΏ½? catch γ‘γ½γγγδ½Ώη¨γγγ«γ―γγγγγΉγͺγγΈγ§γ―γοΏ½? catch γεΌγ³εΊγγΎγγcatch γ―γ¨γ©γΌγ‘γγ»γΌγΈγεΌζ°γ¨γγι’ζ°γε―δΈοΏ½?ι’ζ°γ¨γγ¦εγεγγΎγγcatch γ«ζΈ‘γγγι’ζ°γ«γγ£γ¦θΏγγγδ»»ζοΏ½?ε€γγγγγγΉοΏ½?θ§£ζ±Ίε€γ¨γγ¦δ½Ώη¨γγγΎγγ
γγ©γγ«γ·γ₯γΌγγ£γ³γ°
βSuspense Exception: This is not a real error!β
γγͺγγ― React γ³γ³γγΌγγ³γγΎγγ―γγγ―ι’ζ°οΏ½?ε€ι¨γ§ use γεΌγ³εΊγγ¦γγγγγΎγγ― try-catch γγγγ―ε
γ§ use γεΌγ³εΊγγ¦γγΎγγtry-catch γγγγ―ε
γ§ use γεΌγ³εΊγγ¦γγε ΄εγ―γγ³γ³γγΌγγ³γγγ¨γ©γΌγγ¦γ³γγͺγ§γ©γγγγγγγγγγΉοΏ½? catch γεΌγ³εΊγγ¦γ¨γ©γΌγγγ£γγγγε₯οΏ½?ε€γ§γγγγΉγθ§£ζ±ΊγγΎγγγγ‘γοΏ½?δΎγεη
§γγ¦γγ γγγ
React γ³γ³γγΌγγ³γγΎγγ―γγγ―ι’ζ°οΏ½?ε€ι¨γ§ use γεΌγ³εΊγγ¦γγε ΄εγ―γuse οΏ½?εΌγ³εΊγγ React γ³γ³γγΌγγ³γγΎγγ―γγγ―ι’ζ°γ«η§»εγγΎγγ
function MessageComponent({messagePromise}) {
function download() {
// β the function calling `use` is not a Component or Hook
const message = use(messagePromise);
// ...δΈθ¨οΏ½?ε ΄εγγ³γ³γγΌγγ³γοΏ½?γ―γγΌγΈγ£οΏ½?ε€γ§ use γεΌγ³εΊγγγγ«γγγγ¨γ§γγ³γ³γγΌγγ³γγΎγγ―γγγ―γγ use γεΌγ³εΊγγ¨γγζ‘δ»ΆγζΊγγγγγ«γͺγγΎγγ
function MessageComponent({messagePromise}) {
// β
`use` is being called from a component.
const message = use(messagePromise);
// ...