Next.js 和 Styled Components 在刷新时服务器和客户端之间不同步
Posted
技术标签:
【中文标题】Next.js 和 Styled Components 在刷新时服务器和客户端之间不同步【英文标题】:Next.js and Styled Components go out of sync between the server and the client on refresh 【发布时间】:2021-02-20 17:23:09 【问题描述】:我有一个使用样式化组件的 Next.js 应用程序。在第一次加载任何页面时,没有任何投诉,并且所有内容看起来都样式正确。但是,当我刷新页面时,一切看起来仍然正常,但我收到控制台错误读数:
Warning: Prop `className` did not match. Server: "sc-TXQaF bfnBGK" Client: "sc-bdnylx kKokSB"
我已尝试简化特定组件的样式,但错误仍然存在。我尝试从 DOM 中完全删除该组件,这会导致 DOM 中的下一个元素出现相同的错误。所以这似乎是一个全球性的问题。
我已按照此处找到的使用 Next.js 和样式化组件的指南进行操作:https://github.com/vercel/next.js/tree/master/examples/with-styled-components
我在根目录中有.babelrc
文件:
"presets": ["next/babel"],
"plugins": [["styled-components", "s-s-r": true ]]
我的 pages 目录中有 _document.js
文件:
import Document from 'next/document'
import ServerStyleSheet from 'styled-components'
export default class MyDocument extends Document
static async getInitialProps(ctx)
const sheet = new ServerStyleSheet()
const originalRenderPage = ctx.renderPage
try
ctx.renderPage = () =>
originalRenderPage(
enhanceApp: (App) => (props) =>
sheet.collectStyles(<App ...props />),
)
const initialProps = await Document.getInitialProps(ctx)
return
...initialProps,
styles: (
<>
initialProps.styles
sheet.getStyleElement()
</>
),
finally
sheet.seal()
这是我的样式组件之一的示例:
import styled from 'styled-components';
export const Block = styled.div`
margin: $props => props.small ? '2rem 0' : '4rem 0';
margin-top: $props => props.clearTop ? '0' : null;
`;
...尽管我尝试将其简化为像这样简单的事情,而控制台错误没有改变:
import styled from 'styled-components';
export const Block = styled.div`
position: relative;
`;
最后,这是一个仍然产生错误的愚蠢页面:
import useContext, useEffect from 'react';
import useRouter from 'next/router';
import Layout from '../components/layout';
import Block from '../components/styled/Block';
import userContext from '../context/userContext';;
function Profile()
const router = useRouter();
const loggedIn = useContext(userContext);
useEffect(() =>
if (!loggedIn) router.push('/login');
, [loggedIn]);
return (
<Layout>
<Block>
<h1>Test</h1>
</Block>
</Layout>
)
export default Profile;
我的智慧到此为止。
【问题讨论】:
【参考方案1】:我相信我找到了答案。我没有 babel 样式组件的 dev 依赖项。
npm install babel-plugin-styled-components --save-dev
你的package.json
文件应该有这个:
"devDependencies":
"babel-plugin-styled-components": "^1.11.1"
安装后,连同_document.js
和.babelrc
文件正确放置在您的应用中,您应该不会有任何问题。
【讨论】:
【参考方案2】:我在过去 1 个月里遇到了这个问题,终于找到了适合我的解决方案!
所以这里的解决方案是只从服务器获取样式。
from the docs:
基本上你需要添加一个自定义页面/_document.js(如果你不 有一个)。然后复制样式组件的逻辑以注入 服务器端渲染样式到
<head>
要解决此问题,您需要在 Document 组件中添加类似内容:
import Document from 'next/document'
import ServerStyleSheet from 'styled-components'
export default class MyDocument extends Document
static async getInitialProps(ctx)
const sheet = new ServerStyleSheet()
const originalRenderPage = ctx.renderPage
try
ctx.renderPage = () =>
originalRenderPage(
enhanceApp: (App) => (props) =>
sheet.collectStyles(<App ...props />),
)
const initialProps = await Document.getInitialProps(ctx)
return
...initialProps,
styles: (
<>
initialProps.styles
sheet.getStyleElement()
</>
),
finally
sheet.seal()
最后一步(如果错误仍然存在)是删除缓存:删除 .next 文件夹并重新启动服务器
Next 文档中的完整示例代码是 Here
【讨论】:
以上是关于Next.js 和 Styled Components 在刷新时服务器和客户端之间不同步的主要内容,如果未能解决你的问题,请参考以下文章
是否有可能使用 Next.js + Styled-Components 和静态主机(例如 S3)制定有意义/安全的内容安全策略
在next.js中使用styled-component以及全局主题切换
在 Next.js 中为 styled-jsx 动态添加样式