use
是一个 React API,可让你读取资源的值,例如 Promise 或 上下文。
¥use
is a React API that lets you read the value of a resource like a Promise or context.
const value = use(resource);
参考
¥Reference
use(resource)
在组件中调用 use
来读取 Promise 或 上下文 等资源的值。
¥Call use
in your component to read the value of a resource like a Promise or context.
import { use } from 'react';
function MessageComponent({ messagePromise }) {
const message = use(messagePromise);
const theme = use(ThemeContext);
// ...
与 React 钩子不同,use
可以在循环和条件语句中调用,如 if
。与 React 钩子一样,调用 use
的函数必须是组件或 Hook。
¥Unlike React Hooks, use
can be called within loops and conditional statements like if
. Like React Hooks, the function that calls use
must be a Component or Hook.
当使用 Promise 调用时,use
API 与 Suspense
和 误差边界 集成。当传递给 use
的 Promise 处于挂起状态时,调用 use
的组件会挂起。如果调用 use
的组件包含在 Suspense 边界中,则将显示回退。一旦 Promise 得到解决,Suspense 回退将被使用 use
API 返回的数据由渲染的组件替换。如果传递给 use
的 Promise 被拒绝,则会显示最近的错误边界的回退。
¥When called with a Promise, the use
API integrates with Suspense
and error boundaries. The component calling use
suspends while the Promise passed to use
is pending. If the component that calls use
is wrapped in a Suspense boundary, the fallback will be displayed. Once the Promise is resolved, the Suspense fallback is replaced by the rendered components using the data returned by the use
API. If the Promise passed to use
is rejected, the fallback of the nearest Error Boundary will be displayed.
参数
¥Parameters
-
resource
:这是你要从中读取值的数据源。资源可以是 Promise 或 上下文。¥
resource
: this is the source of the data you want to read a value from. A resource can be a Promise or a context.
返回
¥Returns
use
API 返回从资源读取的值,如 Promise 或 上下文 的解析值。
¥The use
API returns the value that was read from the resource like the resolved value of a Promise or context.
注意事项
¥Caveats
-
use
API 必须在组件或钩子内调用。¥The
use
API must be called inside a Component or a Hook. -
在 服务器组件 中获取数据时,优先选择
async
和await
而不是use
。async
和await
从调用await
的位置开始渲染,而use
在解析数据后重新渲染组件。¥When fetching data in a Server Component, prefer
async
andawait
overuse
.async
andawait
pick up rendering from the point whereawait
was invoked, whereasuse
re-renders the component after the data is resolved. -
与在客户端组件中创建 Promise 相比,更喜欢在 服务器组件 中创建 Promise 并将它们传递给 客户端组件。在客户端组件中创建的 Promise 会在每次渲染时重新创建。从服务器组件传递到客户端组件的 Promise 在重新渲染过程中是稳定的。看这个例子。
¥Prefer creating Promises in Server Components and passing them to Client Components over creating Promises in Client Components. Promises created in Client Components are recreated on every render. Promises passed from a Server Component to a Client Component are stable across re-renders. See this example.
用法
¥Usage
与 use
一起阅读上下文
¥Reading context with use
当 上下文 传递给 use
时,其工作方式与 useContext
类似。虽然 useContext
必须在组件的顶层调用,但 use
可以在条件语句(如 if
)和循环(如 for
)内部调用。use
优于 useContext
,因为它更灵活。
¥When a context is passed to use
, it works similarly to useContext
. While useContext
must be called at the top level of your component, use
can be called inside conditionals like if
and loops like for
. use
is preferred over useContext
because it is more flexible.
import { use } from 'react';
function Button() {
const theme = use(ThemeContext);
// ...
use
为你传递的 上下文 返回的 上下文值。为了确定上下文值,React 搜索组件树并找到上面与该特定上下文最接近的上下文提供者。
¥use
returns the context value for the context you passed. To determine the context value, React searches the component tree and finds the closest context provider above for that particular context.
要将上下文传递给 Button
,请将其或其父组件之一封装到相应的上下文提供程序中。
¥To pass context to a Button
, wrap it or one of its parent components into the corresponding context provider.
function MyPage() {
return (
<ThemeContext.Provider value="dark">
<Form />
</ThemeContext.Provider>
);
}
function Form() {
// ... renders buttons inside ...
}
提供器和 Button
之间有多少层组件并不重要。当 Form
内部任何位置的 Button
调用 use(ThemeContext)
时,它将接收 "dark"
作为值。
¥It doesn’t matter how many layers of components there are between the provider and the Button
. When a Button
anywhere inside of Form
calls use(ThemeContext)
, it will receive "dark"
as the value.
与 useContext
不同,use
可以在条件和循环中调用,如 if
。
¥Unlike useContext
, use
can be called in conditionals and loops like if
.
function HorizontalRule({ show }) {
if (show) {
const theme = use(ThemeContext);
return <hr className={theme} />;
}
return false;
}
use
从 if
语句内部调用,允许你有条件地从 Context 读取值。
¥use
is called from inside a if
statement, allowing you to conditionally read values from a 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 }
将数据从服务器流式传输到客户端
¥Streaming data from the server to the client
通过将 Promise 作为属性从 Server Component 传递到 Client Component,可以将数据从服务器流式传输到客户端。
¥Data can be streamed from the server to the client by passing a Promise as a prop from a Server Component to a 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>
);
}
然后,客户端组件 将 它作为属性收到的 Promise 传递给 use
API。这允许客户端组件从最初由服务器组件创建的Promise读取值。
¥The Client Component then takes the Promise it received as a prop and passes it to the use
API. This allows the Client Component to read the value from the Promise that was initially created by the 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>;
}
由于 Message
封装在 Suspense
中,因此将显示回退,直到 Promise 得到解析。当 Promise 被解析时,该值将由 use
API 读取,并且 Message
组件将替换 Suspense 回退。
¥Because Message
is wrapped in Suspense
, the fallback will be displayed until the Promise is resolved. When the Promise is resolved, the value will be read by the use
API and the Message
component will replace the 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> ); }
深入研究
¥Should I resolve a Promise in a Server or Client Component?
Promise 可以从服务器组件传递到客户端组件,并使用 use
API 在客户端组件中解析。你还可以使用 await
解析服务器组件中的 Promise,并将所需的数据作为属性传递给客户端组件。
¥A Promise can be passed from a Server Component to a Client Component and resolved in the Client Component with the use
API. You can also resolve the Promise in a Server Component with await
and pass the required data to the Client Component as a prop.
export default async function App() {
const messageContent = await fetchMessage();
return <Message messageContent={messageContent} />
}
但是在 服务器组件 中使用 await
将阻止其渲染,直到 await
语句完成。将 Promise 从服务器组件传递到客户端组件可以防止 Promise 阻止服务器组件的渲染。
¥But using await
in a Server Component will block its rendering until the await
statement is finished. Passing a Promise from a Server Component to a Client Component prevents the Promise from blocking the rendering of the Server Component.
处理被拒绝的 Promise
¥Dealing with rejected Promises
在某些情况下,传递给 use
的 Promise 可能会被拒绝。你可以通过以下任一方式处理被拒绝的 Promise:
¥In some cases a Promise passed to use
could be rejected. You can handle rejected Promises by either:
向用户显示带有错误边界的错误
¥Displaying an error to users with an error boundary
如果你想在 Promise 被拒绝时向用户显示错误,你可以使用 误差边界。要使用错误边界,请将调用 use
API 的组件封装在错误边界中。如果传递给 use
的 Promise 被拒绝,则会显示错误边界的回退。
¥If you’d like to display an error to your users when a Promise is rejected, you can use an error boundary. To use an error boundary, wrap the component where you are calling the use
API in an error boundary. If the Promise passed to use
is rejected the fallback for the error boundary will be displayed.
"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
提供替代值
¥Providing an alternative value with Promise.catch
如果你想在传递给 use
的 Promise 被拒绝时提供替代值,你可以使用 Promise 的 catch
方法。
¥If you’d like to provide an alternative value when the Promise passed to use
is rejected you can use the Promise’s catch
method.
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 的解析值。
¥To use the Promise’s catch
method, call catch
on the Promise object. catch
takes a single argument: a function that takes an error message as an argument. Whatever is returned by the function passed to catch
will be used as the resolved value of the Promise.
故障排除
¥Troubleshooting
“Suspense 例外:这不是真正的错误!”
¥“Suspense Exception: This is not a real error!”
你要么在 React 组件或钩子函数之外调用 use
,要么在 try–catch 块中调用 use
。如果你在 try-catch 块内调用 use
,请将组件封装在错误边界中,或调用 Promise 的 catch
来捕获错误并使用另一个值解析 Promise。请参阅这些示例。
¥You are either calling use
outside of a React Component or Hook function, or calling use
in a try–catch block. If you are calling use
inside a try–catch block, wrap your component in an error boundary, or call the Promise’s catch
to catch the error and resolve the Promise with another value. See these examples.
如果你在 React 组件或钩子函数之外调用 use
,请将 use
调用移至 React 组件或钩子函数。
¥If you are calling use
outside a React Component or Hook function, move the use
call to a React Component or Hook function.
function MessageComponent({messagePromise}) {
function download() {
// ❌ the function calling `use` is not a Component or Hook
const message = use(messagePromise);
// ...
相反,在任何组件闭包之外调用 use
,其中调用 use
的函数是组件或 Hook。
¥Instead, call use
outside any component closures, where the function that calls use
is a Component or Hook.
function MessageComponent({messagePromise}) {
// ✅ `use` is being called from a component.
const message = use(messagePromise);
// ...