常见问题 #
安装与配置 #
1. css prop 不生效 #
问题:在组件中使用 css prop 没有效果。
解决方案:
方式一:添加 jsx pragma
/** @jsxImportSource @emotion/react */
import { css } from '@emotion/react'
function Component() {
return <div css={css`color: red;`}>Hello</div>
}
方式二:配置 tsconfig.json
{
"compilerOptions": {
"jsxImportSource": "@emotion/react"
}
}
方式三:配置 Babel
{
"plugins": ["@emotion"]
}
2. 样式闪烁 (FOUC) #
问题:服务端渲染时出现样式闪烁。
解决方案:确保正确提取和注入样式。
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. 类名不匹配 #
问题:服务端和客户端类名不一致。
解决方案:确保使用相同的缓存配置。
const cacheKey = 'my-app'
const serverCache = createCache({ key: cacheKey })
const clientCache = createCache({ key: cacheKey })
样式问题 #
4. 样式优先级问题 #
问题:样式被其他样式覆盖。
解决方案:
方式一:使用更具体的选择器
const Button = styled.button`
&& {
color: red;
}
`
方式二:使用 !important(不推荐)
const Button = styled.button`
color: red !important;
`
方式三:调整样式顺序
const cache = createCache({ key: 'css', prepend: true })
5. 全局样式不生效 #
问题:Global 组件的样式不生效。
解决方案:确保 Global 组件正确放置。
import { Global, css } from '@emotion/react'
function App() {
return (
<>
<Global styles={css`body { margin: 0; }`} />
<AppContent />
</>
)
}
6. 嵌套选择器问题 #
问题:嵌套选择器不生效。
解决方案:确保使用正确的语法。
const Parent = styled.div`
& .child {
color: red;
}
& > .direct-child {
color: blue;
}
`
性能问题 #
7. 渲染性能慢 #
问题:组件渲染变慢。
解决方案:
方式一:提取样式到组件外部
const style = css`padding: 20px;`
function Component() {
return <div css={style}>Content</div>
}
方式二:使用 useMemo 缓存动态样式
const style = useMemo(() => css`
font-size: ${size}px;
`, [size])
方式三:使用 styled 组件
const StyledItem = styled.li`...`
function List({ items }) {
return items.map(item => <StyledItem key={item.id}>{item.name}</StyledItem>)
}
8. 包体积过大 #
问题:打包后体积过大。
解决方案:
方式一:按需导入
import styled from '@emotion/styled'
import { css } from '@emotion/react'
方式二:确保 Tree Shaking
{
"sideEffects": false
}
TypeScript 问题 #
9. 类型错误 #
问题:TypeScript 报类型错误。
解决方案:
方式一:扩展 Theme 接口
declare module '@emotion/react' {
export interface Theme {
colors: {
primary: string
}
}
}
方式二:正确配置 tsconfig.json
{
"compilerOptions": {
"jsxImportSource": "@emotion/react"
}
}
10. Props 类型推断 #
问题:styled 组件的 props 类型推断不正确。
解决方案:
interface ButtonProps {
variant?: 'primary' | 'secondary'
}
const Button = styled.button<ButtonProps>`
background: ${props => props.variant === 'primary' ? '#007bff' : '#6c757d'};
`
主题问题 #
11. 主题不生效 #
问题:ThemeProvider 的主题不生效。
解决方案:确保组件在 ThemeProvider 内部。
import { ThemeProvider } from '@emotion/react'
function App() {
return (
<ThemeProvider theme={theme}>
<AppContent />
</ThemeProvider>
)
}
12. useTheme 返回 undefined #
问题:useTheme 返回 undefined。
解决方案:确保组件被 ThemeProvider 包裹。
function Component() {
const theme = useTheme()
if (!theme) {
throw new Error('useTheme must be used within a ThemeProvider')
}
return <div>...</div>
}
动画问题 #
13. 动画不流畅 #
问题:动画卡顿。
解决方案:
方式一:使用 transform 和 opacity
const Animated = styled.div`
transition: transform 0.3s ease, opacity 0.3s ease;
&:hover {
transform: translateY(-4px);
opacity: 0.9;
}
`
方式二:使用 will-change
const Animated = styled.div`
will-change: transform;
animation: ${keyframes} 1s ease;
`
14. keyframes 不生效 #
问题:定义的动画不生效。
解决方案:确保正确引用 keyframes。
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。
import { CacheProvider } from '@emotion/react'
import createCache from '@emotion/cache'
const cache = createCache({ key: 'css' })
const html = renderToString(
<CacheProvider value={cache}>
<App />
</CacheProvider>
)
16. 水合错误 #
问题:客户端水合失败。
解决方案:确保服务端和客户端使用相同的初始状态。
const ids = window.__EMOTION_IDS__
const cache = createCache({ key: 'css' })
hydrate(
<CacheProvider value={cache}>
<App />
</CacheProvider>,
document.getElementById('root')
)
调试技巧 #
17. 如何调试样式 #
技巧一:使用 React DevTools
查看组件的 props 和样式。
技巧二:使用浏览器开发者工具
检查元素的类名和计算样式。
技巧三:添加调试样式
const DebugBox = styled.div`
outline: 1px solid red;
`
18. 如何查看生成的类名 #
解决方案:使用 emotion-theming 的 label。
const Button = styled.button`
label: Button;
color: red;
`
其他问题 #
19. 与其他 CSS-in-JS 库冲突 #
问题:与其他 CSS-in-JS 库同时使用时出现问题。
解决方案:使用不同的缓存 key。
const emotionCache = createCache({ key: 'emotion' })
const otherCache = createCache({ key: 'other' })
20. CSP (内容安全策略) 问题 #
问题:严格的 CSP 策略导致样式不生效。
解决方案:使用 nonce。
const cache = createCache({
key: 'css',
nonce: 'your-nonce-here',
})
总结 #
以上是 Emotion 使用中的常见问题和解决方案。如果遇到其他问题,可以:
- 查阅官方文档
- 搜索 GitHub Issues
- 在社区提问
祝你在使用 Emotion 的过程中一切顺利!