【发布时间】:2021-08-14 14:02:44
【问题描述】:
关于 next.js 的使用和 react 以实现 SSR 构建在彼此之上的以下问题,所以我想我会把它写成一篇文章。我的主要问题是第三个问题,但我觉得我需要先了解前两个问题才能到达那里。所以我们开始:
1.客户端收到后总是从头开始重新执行整个页面,我说的对吗?
考虑这个 next.js 页面组件:
const Page = () => {
const [state, setState] = useState(getState());
function getState() {
console.log("compute initial state");
return 1;
}
return <>{state}</>;
};
据我所知,getState() 在服务器和客户端都执行。如果我只想在服务器上执行该计算,我必须通过getInitialProps()resp 来完成。 getServersideProps(),对吧?
2.预渲染的文档如果立即丢弃,对客户端有什么价值?
让第一个问题更进一步,如果预渲染文档事件无论如何都要从头开始重新计算,为什么还要将它交给客户端。客户获得初始文件有什么好处?好的,如果客户端根本无法执行js,他们至少有一些东西。但仅此而已吗?
3.这是否意味着我不必在客户端“双重渲染”某些组件?
假设我的部分代码依赖于window,无法在服务器上执行。正如我在不同的articles 中所解释的那样,如果我在我的代码中依赖像typeof window === "undefined" 这样的检查,它可能会导致问题(并做出反应警告)。相反,我认为更好的方法是在第一次渲染后使用useEffect 执行这些功能:
const Page = () => {
const [value, setValue] = useState();
// Effect will be executed after the first render, e.g. never on the server
useEffect(() => {
const value = window.innerWidth; // Some computations or subscriptions that depend on window
setValue(value)
}, []);
return (
<>
{!value && <h1>value pending ...</h1>}
{value && <h1>{value}</h1>}
</>
);
};
现在,使用这种模式,从 SSR 的角度来看,应用程序很好。但是我正在引入在客户端已经完成的额外工作:即使window 是在第一次渲染时定义的,它也只能在第二次渲染时使用。
对于这个较小的示例,这并没有起到很大的作用,但在较大的应用程序中,可能会出现闪烁,因为不必要的第一次渲染会在几毫秒后更新。此外,代码变得更难阅读,更容易出错。
我想要的解决方案与上面的第一个问题有关:我能否以某种方式避免应用程序从头开始,而是直接从第二个渲染开始?到目前为止我错过了某种模式吗?
注意:当然我可以重写组件来简单地检查window是否被定义:
return (
<>
<h1>{window ? window.innerWidth : "value pending ..."}</h1>
</>
);
但是,这将导致反应警告并导致我在上面喜欢的文章中描述的其他问题。另见react docs:
React 期望在服务器和客户端之间呈现的内容是相同的。它可以修补文本内容的差异,但您应该将不匹配视为错误并修复它们。
非常感谢您的帮助!
【问题讨论】:
标签: reactjs next.js server-side-rendering