如何修复React中emotion/twin.macro的CSS属性异常问题?
React + twin.macro + Emotion 配置故障排查与解决方案
问题现状
使用react-app-rewired自定义Babel配置适配twin.macro,但出现以下问题:
- 组件中使用
tw属性后,编译生成的DOM带有错误提示文本:You have tried to stringify object returned from 'css' function... - 移除组件顶部的
/** @jsxRuntime classic */注释后,触发React自动JSX运行时报错,怀疑react-app-rewired未生效 - 最初引入
react-app-rewired是为解决css属性显示为[Object object]的问题,希望能修复该问题并移除react-app-rewired依赖
当前配置文件
package.json
{ "name": "my app", "version": "0.1.0", "private": true, "dependencies": { "@date-io/date-fns": "^2.16.0", "@emotion/styled": "^11.10.5", "@mui/icons-material": "^5.10.3", "@mui/material": "^5.10.5", "@mui/x-data-grid": "^5.17.8", "@mui/x-date-pickers": "^5.0.5", "@reduxjs/toolkit": "^1.8.5", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.4.3", "@types/jest": "^27.5.2", "@types/node": "^17.0.45", "@types/react": "^18.0.20", "@types/react-dom": "^18.0.6", "axios": "^0.27.2", "d3": "^7.6.1", "date-fns": "^2.29.3", "html-react-parser": "^3.0.4", "http-proxy-middleware": "^2.0.6", "material-ui-popup-state": "^4.1.0", "radash": "^7.1.0", "react": "^18.2.0", "react-csv": "^2.2.2", "react-dom": "^18.2.0", "react-redux": "^8.0.2", "react-router-dom": "^6.4.0", "react-window": "^1.8.7", "recharts": "^2.1.14", "resize-observer-polyfill": "^1.5.1", "twin.macro": "^3.1.0", "typescript": "^4.9.4", "web-vitals": "^2.1.4" }, "devDependencies": { "@babel/core": "^7.20.7", "@emotion/babel-preset-css-prop": "^11.10.0", "@types/d3": "^7.4.0", "@types/react-csv": "^1.1.3", "@types/react-window": "^1.8.5", "@types/styled-components": "^5.1.26", "autoprefixer": "^10.4.13", "babel-plugin-macros": "^3.1.0", "babel-plugin-twin": "^1.1.0", "customize-cra": "^1.0.0", "postcss": "^8.4.20", "react-app-rewired": "^2.2.1", "react-scripts": "^5.0.1", "tailwindcss": "^3.2.4" }, "scripts": { "start": "react-app-rewired start", "build": "react-app-rewired build", "test": "react-app-rewired test" }, "eslintConfig": { "extends": ["react-app", "react-app/jest"] }, "browserslist": { "production": [">0.2%", "not dead", "not op_mini all"], "development": ["last 1 chrome version", "last 1 firefox version", "last 1 safari version"] } }
.babelrc
{ "plugins": ["babel-plugin-twin", "babel-plugin-macros"], "presets": ["@emotion/babel-preset-css-prop"] }
babel-plugin-macros.config.js
module.exports = { twin: { preset: "emotion" } };
config-overrides.js
const { useBabelRc, override } = require("customize-cra"); module.exports = override(useBabelRc());
测试组件
/** @jsxRuntime classic */ /** @jsx jsx */ import { jsx } from '@emotion/react' const StatsHeader = ({ status, title }: Props) => ( <div tw="bg-red-100"> <span tw="text-red-500">Hello</span> </div> );
解决方案:移除react-app-rewired的配置方案
1. 清理依赖(可选,彻底移除rewired相关工具)
npm uninstall react-app-rewired customize-cra
2. 重构Babel配置文件
删除.babelrc,新建babel.config.js,内容如下:
module.exports = { presets: [ // 保留CRA默认预设,仅在开发环境加载避免冲突 process.env.NODE_ENV === 'development' && 'react-app', '@emotion/babel-preset-css-prop', ].filter(Boolean), plugins: ['babel-plugin-twin', 'babel-plugin-macros'], };
3. 恢复package.json的scripts指令
将scripts改回CRA默认格式:
"scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test" }
4. 调整组件的JSX指令
移除/** @jsxRuntime classic */注释,仅保留Emotion的JSX绑定:
/** @jsx jsx */ import { jsx } from '@emotion/react' const StatsHeader = ({ status, title }: Props) => ( <div tw="bg-red-100"> <span tw="text-red-500">Hello</span> </div> );
核心修复逻辑
- 确保Babel同时加载CRA默认预设与Emotion的css-prop预设,避免JSX运行时冲突
babel-plugin-twin优先于babel-plugin-macros加载,保证twin属性被正确编译为Emotion可识别的css对象- 移除经典JSX运行时强制声明,让Emotion与React 18的自动运行时兼容
内容的提问来源于stack exchange,提问作者serlingpa
相关产品推荐
相关产品推荐

