Emotion 的 css 函数需用 useMemo 缓存以避免重复注入样式;styled 组件需确保 props 可序列化且引用更新;SSR 时必须复用同一 cache 实例;混用库时应设唯一 key 并隔离插入点。

Emotion 的 css 函数怎么写才不重复注入样式?
Emotion 的 css 函数每次调用都会生成唯一 class 名,但若在组件内部无条件调用(比如没加 useMemo),会导致样式规则重复插入 <style> 标签——尤其在严格模式或快速重渲染时,DevTools 里能看到成堆的冗余 .css-xxx 规则。
- 把动态样式逻辑包进
useMemo,依赖项只含真正影响样式的变量 - 避免在 render 中直接调用
css({ color: props.color }),改用useMemo(() => css({ color: props.color }), [props.color]) - 如果只是条件切换颜色/尺寸等简单值,优先用 CSS 自定义属性(
style={{ '--text-color': props.color }})配合静态css规则,比运行时拼样式更轻量
const buttonStyles = useMemo(
() => css({
backgroundColor: theme === 'dark' ? '#333' : '#fff',
border: `1px solid ${borderColor}`,
}),
[theme, borderColor]
);用 styled 创建带 props 动态样式的组件,为什么 className 不变但样式没更新?
styled 生成的组件会缓存样式规则,但只对「首次传入的 props」做一次计算;如果后续 props 改变但未触发重新计算(比如对象引用没变、或用了非响应式值),样式就不会更新。
- 确保传给
styled组件的 props 是可序列化的基础类型(string、number、boolean),避免直接传obj或function - 若必须基于复杂对象推导样式,先在组件内用
useMemo提取关键字段,再透传给 styled 组件 - 注意 React.memo 包裹的组件可能阻止 props 更新向下传递,导致 styled 内部函数收不到新值
const Box = styled.div`
width: ${props => props.width}px;
opacity: ${props => props.active ? 1 : 0.6};
`;服务端渲染(SSR)下 Emotion 样式丢失或闪屏,关键在哪?
SSR 时 Emotion 需同步收集所有组件中生成的样式,再注入到 HTML 的 <head> 中;若客户端 hydration 时样式上下文不一致(比如没传 cache 或 cache 实例不同),就会漏掉部分规则,造成首屏无样式或 layout shift。
- 服务端必须创建唯一
cache实例,并通过CacheProvider注入到整个 React 树 - 客户端需复用同一份
cache(不能 new 一个),通常从全局变量或模块缓存中取 - Next.js 用户注意:
@emotion/server的renderStylesToString必须配合extractCritical使用,且不能跳过getInitialProps或getServerSideProps中的样式提取步骤
常见错误:createCache() 在每个请求里都新建,导致客户端无法匹配服务端生成的 class 名。
立即学习“前端免费学习笔记(深入)”;
Emotion 和 CSS-in-JS 其他库(如 Styled Components)混用时,全局样式冲突怎么防?
Emotion 默认使用 css 和 styled 注入样式,而 Styled Components 也往 <head> 插 <style>,两者 class 命名规则不同但作用域重叠,容易出现权重竞争或覆盖。
- 显式为 Emotion 设置
key(如createCache({ key: 'emotion' })),让它的<style>标签带上data-emotion属性,便于调试和隔离 - 避免在同一个项目中同时用
css和styled去写同一类 UI 组件,选一个主方案,另一个仅用于临时适配遗留代码 - 如果必须共存,把 Emotion 的插入点移到
<head>最前(用container选项指定 DOM 节点),确保它优先级高于其他库
最麻烦的是伪类选择器(:hover、::before)被不同库生成的规则互相覆盖,这时候得靠 specificity + !important 应急,但说明架构已经失衡了。


















