跳到主要内容

使用 use 读取资源

use 如何读取尚未完成的 Promise?​

  • 资源读取: use(promise) 在渲染中读取结果,待完成时挂起最近的 Suspense 边界,成功后继续渲染,失败交给错误边界;
  • 稳定 Promise: 必须复用缓存的 Promise,不能每次客户端渲染都创建新 Promise,否则重试永远面对新资源;
  • 服务端输入: Server Component 可把 Promise 传给 Client Component,其最终结果必须能跨边界序列化;
import { Suspense, use } from "react";

function Message({ messagePromise }) {
const message = use(messagePromise);
return <p>{message}</p>;
}

function Page({ messagePromise }) {
return (
<Suspense fallback={<p>加载中……</p>}>
<Message messagePromise={messagePromise} />
</Suspense>
);
}

use 的调用规则与 Hook 有何区别?​

  • 允许分支: use 不是普通 Hook,可以放在条件和循环里,但仍必须位于组件或 Hook 中,不能在任意普通函数调用;
  • 异常边界: 不把 use 包在 try/catch 中,失败使用错误边界处理,或预先让 Promise.catch 转成替代值;
  • 服务端偏好: async Server Component 获取数据通常优先 await,使执行从等待处继续,而不是按客户端模式组织资源读取;

use 如何读取 Context?​

  • 读取规则: use(SomeContext) 获取最近祖先提供者的值,可以在条件分支中读取;提供与默认值契约仍遵循 Context 主笔记;
  • 服务端限制: 当前 Server Components 不支持用 use 读取 Context,不要把客户端 Context 共享模式直接照搬到服务器;

如何声明一个只在浏览器渲染的组件?​

  • Browser 资源: use(browser(reason)) 在服务端保留最近 Suspense 的 fallback,在浏览器继续渲染;单独调用 browser 没有效果,也不要 throw 返回值;
  • 边界条件: 服务端必须存在 Suspense,RSC 应用中应从 Client Component 调用,不能在 Server Component 中直接使用;
  • 版本核对: 使用 browser 前核对项目实际 react-dom 导出,不把较新能力默认当作所有 React 19 小版本都有;
import { use } from "react";
import { browser } from "react-dom";

function BrowserContent() {
use(browser("需要浏览器尺寸"));
return <p>浏览器宽度:{window.innerWidth}</p>;
}
import { Suspense } from "react";

function Page() {
return (
<Suspense fallback={<p>浏览器内容准备中……</p>}>
<BrowserContent />
</Suspense>
);
}
  • 服务端输出: 页面先显示 fallback,浏览器接手后才运行需要 window 的内容;单独加 'use client' 并不能替代这个跳过服务端渲染的边界;