use
là một API của React cho phép bạn đọc giá trị của một tài nguyên như Promise hoặc context.
const value = use(resource);
Tham khảo
use(resource)
Gọi use
trong component của bạn để đọc giá trị của một tài nguyên như Promise hoặc context.
import { use } from 'react';
function MessageComponent({ messagePromise }) {
const message = use(messagePromise);
const theme = use(ThemeContext);
// ...
Không giống như React Hooks, use
có thể được gọi bên trong các vòng lặp và các câu lệnh điều kiện như if
. Giống như React Hooks, hàm gọi use
phải là một Component hoặc Hook.
Khi được gọi với một Promise, API use
tích hợp với Suspense
và error boundaries. Component gọi use
sẽ tạm dừng trong khi Promise được truyền cho use
đang ở trạng thái pending. Nếu component gọi use
được bao bọc trong một Suspense boundary, fallback sẽ được hiển thị. Khi Promise được resolve, Suspense fallback sẽ được thay thế bằng các component được render bằng dữ liệu trả về bởi API use
. Nếu Promise được truyền cho use
bị reject, fallback của Error Boundary gần nhất sẽ được hiển thị.
Tham số
resource
: Đây là nguồn dữ liệu mà bạn muốn đọc giá trị. Một resource có thể là một Promise hoặc một context.
Giá trị trả về
API use
trả về giá trị được đọc từ resource, chẳng hạn như giá trị đã được resolve của một Promise hoặc context.
Lưu ý
- API
use
phải được gọi bên trong một Component hoặc một Hook. - Khi tìm nạp dữ liệu trong một Server Component, hãy ưu tiên
async
vàawait
hơnuse
.async
vàawait
tiếp tục quá trình render từ điểm màawait
được gọi, trong khiuse
render lại component sau khi dữ liệu được resolve. - Ưu tiên tạo Promises trong Server Components và truyền chúng cho Client Components hơn là tạo Promises trong Client Components. Promises được tạo trong Client Components sẽ được tạo lại trên mỗi lần render. Promises được truyền từ một Server Component sang một Client Component sẽ ổn định trên các lần re-render. Xem ví dụ này.
Cách sử dụng
Đọc context với use
Khi một context được truyền cho use
, nó hoạt động tương tự như useContext
. Trong khi useContext
phải được gọi ở cấp cao nhất của component, use
có thể được gọi bên trong các điều kiện như if
và các vòng lặp như for
. use
được ưu tiên hơn useContext
vì nó linh hoạt hơn.
import { use } from 'react';
function Button() {
const theme = use(ThemeContext);
// ...
use
trả về giá trị context cho context mà bạn đã truyền. Để xác định giá trị context, React tìm kiếm trên cây component và tìm context provider gần nhất ở phía trên cho context cụ thể đó.
Để truyền context cho một Button
, hãy bọc nó hoặc một trong các component cha của nó vào context provider tương ứng.
function MyPage() {
return (
<ThemeContext.Provider value="dark">
<Form />
</ThemeContext.Provider>
);
}
function Form() {
// ... renders buttons inside ...
}
Không quan trọng có bao nhiêu lớp component giữa provider và Button
. Khi một Button
ở bất kỳ đâu bên trong Form
gọi use(ThemeContext)
, nó sẽ nhận được dark
làm giá trị.
Không giống như useContext
, use
có thể được gọi trong các điều kiện và vòng lặp như if
.
function HorizontalRule({ show }) {
if (show) {
const theme = use(ThemeContext);
return <hr className={theme} />;
}
return false;
}
use
được gọi từ bên trong một câu lệnh if
, cho phép bạn đọc có điều kiện các giá trị từ một Context.
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 }
Truyền dữ liệu từ server đến client
Dữ liệu có thể được truyền từ server đến client bằng cách truyền một Promise như một prop từ một Server Component đến một Client Component.
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>
);
}
Client Component sau đó nhận Promise mà nó nhận được như một prop và truyền nó cho API use
. Điều này cho phép Client Component đọc giá trị từ Promise ban đầu được tạo bởi Server Component.
// message.js
'use client';
import { use } from 'react';
export function Message({ messagePromise }) {
const messageContent = use(messagePromise);
return <p>Here is the message: {messageContent}</p>;
}
Vì Message
được bao bọc trong Suspense
, fallback sẽ được hiển thị cho đến khi Promise được resolve. Khi Promise được resolve, giá trị sẽ được đọc bởi API use
và component Message
sẽ thay thế 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> ); }
Tìm hiểu sâu
Một Promise có thể được truyền từ một Server Component đến một Client Component và được resolve trong Client Component với API use
. Bạn cũng có thể resolve Promise trong một Server Component với await
và truyền dữ liệu cần thiết cho Client Component như một prop.
export default async function App() {
const messageContent = await fetchMessage();
return <Message messageContent={messageContent} />
}
Nhưng sử dụng await
trong một Server Component sẽ chặn quá trình render của nó cho đến khi câu lệnh await
kết thúc. Truyền một Promise từ một Server Component đến một Client Component ngăn Promise chặn quá trình render của Server Component.
Xử lý các Promise bị reject
Trong một số trường hợp, một Promise được truyền cho use
có thể bị reject. Bạn có thể xử lý các Promise bị reject bằng một trong hai cách:
Hiển thị lỗi cho người dùng bằng error boundary
Nếu bạn muốn hiển thị lỗi cho người dùng khi một Promise bị reject, bạn có thể sử dụng một error boundary. Để sử dụng một error boundary, hãy bọc component nơi bạn đang gọi API use
trong một error boundary. Nếu Promise được truyền cho use
bị reject, fallback cho error boundary sẽ được hiển thị.
"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>; }
Cung cấp một giá trị thay thế với Promise.catch
Nếu bạn muốn cung cấp một giá trị thay thế khi Promise được truyền cho use
bị reject, bạn có thể sử dụng phương thức catch
của Promise.
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>
);
}
Để sử dụng phương thức catch
của Promise, hãy gọi catch
trên đối tượng Promise. catch
nhận một đối số duy nhất: một hàm nhận một thông báo lỗi làm đối số. Bất cứ điều gì được trả về bởi hàm được truyền cho catch
sẽ được sử dụng làm giá trị đã được resolve của Promise.
Khắc phục sự cố
“Suspense Exception: This is not a real error!”
Bạn đang gọi use
bên ngoài một React Component hoặc hàm Hook, hoặc gọi use
trong một khối try-catch. Nếu bạn đang gọi use
bên trong một khối try-catch, hãy bọc component của bạn trong một error boundary, hoặc gọi catch
của Promise để bắt lỗi và resolve Promise với một giá trị khác. Xem các ví dụ này.
Nếu bạn đang gọi use
bên ngoài một React Component hoặc hàm Hook, hãy di chuyển lệnh gọi use
đến một React Component hoặc hàm Hook.
function MessageComponent({messagePromise}) {
function download() {
// ❌ hàm gọi `use` không phải là một Component hoặc Hook
const message = use(messagePromise);
// ...
Thay vào đó, hãy gọi use
bên ngoài bất kỳ closure component nào, nơi hàm gọi use
là một Component hoặc Hook.
function MessageComponent({messagePromise}) {
// ✅ `use` đang được gọi từ một component.
const message = use(messagePromise);
// ...