You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React+Emotion中:nth-child触发SSR报错疑问:客户端为何出现该提示?

为什么纯客户端运行的React项目用Emotion会触发SSR相关的:nth-child报错?

问题场景

我在React项目中用Emotion给特定div写样式,代码是这样的:

export const StyledItem = styled('div')(() => ({ '&:nth-child(1) > div:nth-child(1)': { paddingBottom: '1px' } }))

结果Chrome控制台弹出报错:The pseudo class ":nth-child" is potentially unsafe when doing server-side rendering. Try changing it to ":nth-of-type"。换成:nth-of-type之后报错就没了。我的项目依赖是:

"dependencies": { 
  "@emotion/core": "^10.0.28", 
  "@emotion/styled": "^10.0.27", 
  "react": "^16.13.1", 
  "@storybook/react": "^5.3.13", 
  /* 其他依赖 */ 
}

明明我是在客户端运行项目,为啥会出现SSR相关的报错提示?


原因拆解

这个问题其实和你当前是否在客户端运行无关,主要是两个因素共同导致的:

  1. Emotion的全局安全校验逻辑
    Emotion的样式解析器对所有选择器都会做统一的安全检查,不管你的项目是纯客户端还是SSR。:nth-child的匹配规则依赖父元素下所有子元素的位置排序——如果在SSR场景下,服务端和客户端渲染的DOM结构有一丁点差异(比如某个子元素的渲染条件不同),就会导致样式匹配不一致,触发hydration失败。所以Emotion直接把这类选择器标记为“潜在不安全”,这个校验是全局生效的,不会区分运行环境。

  2. Storybook的环境影响
    你项目里用到的@storybook/react@5.3.13,这个版本的Storybook内部其实包含了SSR相关的逻辑(哪怕你是在浏览器里查看Storybook)。Emotion会检测到环境中存在SSR相关的标识,从而触发这个安全提示,哪怕你实际并没有做项目的SSR渲染。


可选的解决方式

除了你已经试过的替换为:nth-of-type,还有两个方向可以选择:

  • 用unsafeSelector绕过校验(不推荐)
    如果你百分百确定自己的场景不会涉及SSR,也不会出现DOM结构不一致的问题,可以用Emotion提供的unsafeSelector跳过检查:
import { unsafeSelector } from '@emotion/styled'

export const StyledItem = styled('div')(() => ({
  [unsafeSelector('&:nth-child(1) > div:nth-child(1)')]: { paddingBottom: '1px' }
}))

但要注意,这么做相当于关闭了Emotion的安全防护,后续如果项目引入SSR,很容易出现hydration错误,所以谨慎使用。

  • 升级Emotion到新版本
    你现在用的是Emotion 10的旧版本,在Emotion 11及以后的版本中,这个提示逻辑做了优化,会更精准地判断当前环境是否真的是SSR,减少不必要的报错。如果项目允许的话,升级到最新稳定版是更稳妥的长期方案。

内容的提问来源于stack exchange,提问作者norbitrial

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 21:02:54