ice Suspense SSR 下数据如何流式返回

rqmkfv5c  于 2022-12-31  发布在  其他
关注(0)|答案(1)|浏览(167)

React 18 提出和支持了 Suspense SSR 的概念:页面中数据请求耗时较长的组件,可以流式返回,并被延迟 Hydrate

reactwg/react-18#37

参考 React 的 官方 Demo , ICE 也对应跑了一个 Demo https://github.com/ice-lab/ice-next/pull/645/files

暴露的问题是:流式返回的组件,如何回传对应的数据给 Client,用于 Hydrate?

假设 Comments 是一个有数据请求,并被流式返回的组件

<Suspense fallback={<div>Loading...</div>}>
   <Comments />
</Suspense>

Comments 内部做了数据请求,请求未完成时,页面渲染的为 Loading 状态

export default function Comments() {
  const comments = useData();
  return (
    <>
      {comments.map((comment, i) => (
        <p className="comment" key={i}>
          {comment}
        </p>
      ))}
    </>
  );
}

我们知道 SSR 时,Server 传递给 Client 端的内容为 html 片段,当 Client 接受到 html 后,会基于 数据JS Bundle , 重新创建 VDom,进行 Hydrate。

Suspense SSR 下, Comments 的 html 片段是由 React 控制返回的,然后 React 并没有对应的返回 Comments 需要消费的数据,因此 Client 端是无法进行 Hydrate 的。

在 React 的 官方 DemoComments 在 Client 端消费的是一份写死数据(也就是说被构建到 Bundle 中)

React 的 RFC 下也有人提到了这个问题,reactwg/react-18#37 (comment)

sebmarkbage 给的解决方案是可以通过 embedded script tags 来传递,但在 React 的 html 流之外,如何追加额外 script 标签似乎也不容易。

1cklez4t

1cklez4t1#

所以合理的方式应该就是结合 server component 进行处理?

export default async function Comments() {
  let comments = await getData(...);
  // ...
}

相关问题