当浏览器样式与 nextjs 中带有情感样式组件的服务器不同时,样式不适用于第一个客户端渲染(也不是之后)
Posted
技术标签:
【中文标题】当浏览器样式与 nextjs 中带有情感样式组件的服务器不同时,样式不适用于第一个客户端渲染(也不是之后)【英文标题】:Styles not applying on first client render (nor after) when browser styles different from server in nextjs with emotion styled components 【发布时间】:2021-11-02 00:55:53 【问题描述】:当前行为:
当有一个样式有条件地应用在浏览器上时,即使组件运行并且浏览器 props 被正确传入,来自服务器的样式也不会改变。从服务器发回的 html 保留在页面上,即使在传递新的基于浏览器的 props 的客户端上第一次渲染之后,组件仍会继续显示服务器样式。这是在 nextjs 应用程序中,使用情感 11
我觉得这必须在某个地方进行讨论,但我整天梳理了 SO、这些问题和 nextjs 问题,但没有发现任何描述确切问题的信息,也没有找到解决方法。
重现: Codesandbox 显示在服务器上具有一组样式的组件,然后在浏览器上时应切换到另一组样式
https://codesandbox.io/s/cool-worker-meil8?file=/package.json:200-335
在服务器上,该框呈现为红色,因为 process.browser 为 false。在浏览器上,isBrowser 属性为 true,所以 js 运行后框应该是蓝色的。但是,尽管控制台日志显示样式化组件实际上确实在客户端上运行 isBrowser true 并且背景颜色设置为蓝色,但该框仍然是红色(这不在沙箱中,但我有的唯一方法发现强制组件实际更改颜色是通过客户端导航或某种重新呈现组件的单独强制状态更新。
预期行为:
我希望服务器发回基于服务器版本的组件的 html/styles,然后在客户端上的第一次渲染之后,组件应该读取基于浏览器的样式并更新以匹配基于样式关闭浏览器道具。
环境信息: 顺便说一下,这个代码框是使用代码框上的 nextjs 的基本版本构建的。除了添加情感,我没有修改任何东西
以下是沙盒中的 deps:
"@emotion/react": "11.4.1"
"@emotion/styled": "11.3.0"
“下一个”:“最新”
“反应”:“17.0.2”
“react-dom”:“17.0.2”
【问题讨论】:
【参考方案1】:这似乎不是一个特定于情感的问题,但实际上是由于较新版本的 react 不会区分 dom 水合,而是保留 html 同时仍然生成正确的组件树(因此 js 运行,导致我感到困惑,但 dom 无法与组件树显示的内容相匹配)。
如果其他人遇到这种情况,解决方案是使用这样的组件,它立即在服务器上渲染一个组件,然后在客户端通过在 useLayoutEffect 中设置 isMounted 状态触发渲染(这不会运行/rerender 在服务器上)然后呈现客户端组件。大致思路如下:
https://github.com/vercel/next.js/discussions/14469
【讨论】:
以上是关于当浏览器样式与 nextjs 中带有情感样式组件的服务器不同时,样式不适用于第一个客户端渲染(也不是之后)的主要内容,如果未能解决你的问题,请参考以下文章