常见问题 #

安装与配置 #

1. css prop 不生效 #

问题:在组件中使用 css prop 没有效果。

解决方案

方式一:添加 jsx pragma

jsx
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react'

function Component() {
  return <div css={css`color: red;`}>Hello</div>
}

方式二:配置 tsconfig.json

json
{
  "compilerOptions": {
    "jsxImportSource": "@emotion/react"
  }
}

方式三:配置 Babel

json
{
  "plugins": ["@emotion"]
}

2. 样式闪烁 (FOUC) #

问题:服务端渲染时出现样式闪烁。

解决方案:确保正确提取和注入样式。

jsx
import createEmotionServer from '@emotion/server/create-instance'
import createCache from '@emotion/cache'

const cache = createCache({ key: 'css' })
const { extractCritical } = createEmotionServer(cache)

const { html, css, ids } = extractCritical(renderedHtml)

3. 类名不匹配 #

问题:服务端和客户端类名不一致。

解决方案:确保使用相同的缓存配置。

jsx
const cacheKey = 'my-app'

const serverCache = createCache({ key: cacheKey })
const clientCache = createCache({ key: cacheKey })

样式问题 #

4. 样式优先级问题 #

问题:样式被其他样式覆盖。

解决方案

方式一:使用更具体的选择器

jsx
const Button = styled.button`
  && {
    color: red;
  }
`

方式二:使用 !important(不推荐)

jsx
const Button = styled.button`
  color: red !important;
`

方式三:调整样式顺序

jsx
const cache = createCache({ key: 'css', prepend: true })

5. 全局样式不生效 #

问题:Global 组件的样式不生效。

解决方案:确保 Global 组件正确放置。

jsx
import { Global, css } from '@emotion/react'

function App() {
  return (
    <>
      <Global styles={css`body { margin: 0; }`} />
      <AppContent />
    </>
  )
}

6. 嵌套选择器问题 #

问题:嵌套选择器不生效。

解决方案:确保使用正确的语法。

jsx
const Parent = styled.div`
  & .child {
    color: red;
  }
  
  & > .direct-child {
    color: blue;
  }
`

性能问题 #

7. 渲染性能慢 #

问题:组件渲染变慢。

解决方案

方式一:提取样式到组件外部

jsx
const style = css`padding: 20px;`

function Component() {
  return <div css={style}>Content</div>
}

方式二:使用 useMemo 缓存动态样式

jsx
const style = useMemo(() => css`
  font-size: ${size}px;
`, [size])

方式三:使用 styled 组件

jsx
const StyledItem = styled.li`...`

function List({ items }) {
  return items.map(item => <StyledItem key={item.id}>{item.name}</StyledItem>)
}

8. 包体积过大 #

问题:打包后体积过大。

解决方案

方式一:按需导入

jsx
import styled from '@emotion/styled'
import { css } from '@emotion/react'

方式二:确保 Tree Shaking

json
{
  "sideEffects": false
}

TypeScript 问题 #

9. 类型错误 #

问题:TypeScript 报类型错误。

解决方案

方式一:扩展 Theme 接口

tsx
declare module '@emotion/react' {
  export interface Theme {
    colors: {
      primary: string
    }
  }
}

方式二:正确配置 tsconfig.json

json
{
  "compilerOptions": {
    "jsxImportSource": "@emotion/react"
  }
}

10. Props 类型推断 #

问题:styled 组件的 props 类型推断不正确。

解决方案

tsx
interface ButtonProps {
  variant?: 'primary' | 'secondary'
}

const Button = styled.button<ButtonProps>`
  background: ${props => props.variant === 'primary' ? '#007bff' : '#6c757d'};
`

主题问题 #

11. 主题不生效 #

问题:ThemeProvider 的主题不生效。

解决方案:确保组件在 ThemeProvider 内部。

jsx
import { ThemeProvider } from '@emotion/react'

function App() {
  return (
    <ThemeProvider theme={theme}>
      <AppContent />
    </ThemeProvider>
  )
}

12. useTheme 返回 undefined #

问题:useTheme 返回 undefined。

解决方案:确保组件被 ThemeProvider 包裹。

jsx
function Component() {
  const theme = useTheme()
  
  if (!theme) {
    throw new Error('useTheme must be used within a ThemeProvider')
  }
  
  return <div>...</div>
}

动画问题 #

13. 动画不流畅 #

问题:动画卡顿。

解决方案

方式一:使用 transform 和 opacity

jsx
const Animated = styled.div`
  transition: transform 0.3s ease, opacity 0.3s ease;
  
  &:hover {
    transform: translateY(-4px);
    opacity: 0.9;
  }
`

方式二:使用 will-change

jsx
const Animated = styled.div`
  will-change: transform;
  animation: ${keyframes} 1s ease;
`

14. keyframes 不生效 #

问题:定义的动画不生效。

解决方案:确保正确引用 keyframes。

jsx
import { keyframes } from '@emotion/react'

const fadeIn = keyframes`
  from { opacity: 0; }
  to { opacity: 1; }
`

const Animated = styled.div`
  animation: ${fadeIn} 1s ease;
`

SSR 问题 #

15. 样式提取失败 #

问题:服务端样式提取失败。

解决方案:确保正确使用 CacheProvider。

jsx
import { CacheProvider } from '@emotion/react'
import createCache from '@emotion/cache'

const cache = createCache({ key: 'css' })

const html = renderToString(
  <CacheProvider value={cache}>
    <App />
  </CacheProvider>
)

16. 水合错误 #

问题:客户端水合失败。

解决方案:确保服务端和客户端使用相同的初始状态。

jsx
const ids = window.__EMOTION_IDS__

const cache = createCache({ key: 'css' })

hydrate(
  <CacheProvider value={cache}>
    <App />
  </CacheProvider>,
  document.getElementById('root')
)

调试技巧 #

17. 如何调试样式 #

技巧一:使用 React DevTools

查看组件的 props 和样式。

技巧二:使用浏览器开发者工具

检查元素的类名和计算样式。

技巧三:添加调试样式

jsx
const DebugBox = styled.div`
  outline: 1px solid red;
`

18. 如何查看生成的类名 #

解决方案:使用 emotion-theming 的 label。

jsx
const Button = styled.button`
  label: Button;
  color: red;
`

其他问题 #

19. 与其他 CSS-in-JS 库冲突 #

问题:与其他 CSS-in-JS 库同时使用时出现问题。

解决方案:使用不同的缓存 key。

jsx
const emotionCache = createCache({ key: 'emotion' })
const otherCache = createCache({ key: 'other' })

20. CSP (内容安全策略) 问题 #

问题:严格的 CSP 策略导致样式不生效。

解决方案:使用 nonce。

jsx
const cache = createCache({
  key: 'css',
  nonce: 'your-nonce-here',
})

总结 #

以上是 Emotion 使用中的常见问题和解决方案。如果遇到其他问题,可以:

  1. 查阅官方文档
  2. 搜索 GitHub Issues
  3. 在社区提问

祝你在使用 Emotion 的过程中一切顺利!

最后更新:2026-03-28