@emotion在React17的适配问题(@jsxImportSource/@jsxRuntime的作用)

问题

React 17 运行时( jsx 支持)的自动导入破坏了 @emotion 自身运行时的支持,从而将导致两种错误:

直接使用了 css props 返回值
import { jsx, css } from '@emotion/react'

const GreenText = css`
  color: green;
`

export default function Home() {
  return (
    <div css={GreenText}>Css props style</div>
  )
}

将会导致:

You have tried to stringify object returned from css function. It isn’t supposed to be used directly (e.g. as value of the className prop), but rather handed to emotion so it can handle it (e.g. as value of css prop).

由于此处 jsx 运行时未导入(因为未使用),所以使得 css props 返回值无法转化。

直接使用了 css props object 返回值
import { jsx, css } from '@emotion/react'

const GreenText = {
  color: 'green',
}

export default function Home() {
  return (
    <div css={GreenText}>Css props style</div>
  )
}

将导致:

<div css="[object Object]">Css props style</div>

由于直接使用了返回的 object ,所以自动 toString 做了隐式转换。

解决

第一类方案是从解决运行时未导入入手。

指定旧的运行时导入模式
/** @jsxRuntime classic */
/** @jsx jsx */
import { css, jsx } from '@emotion/react'
  • @jsxRuntime classic :使用旧版传统模式手动导入运行时

  • @jsx jsx :指明下一行为运行时的导入

注:如果仅使用 @jsx jsx 导入运行时,而不指明旧版模式,将会冲突报错

SyntaxError: …\index.jsx: pragma and pragmaFrag cannot be set when runtime is automatic.

因为 React 17 已经默认采用了新版自动导入运行时。

指定额外导入运行时
/** @jsxImportSource @emotion/react */

只需要添加这一行手工指明导入 @emotion/react 下的所有运行时即可,此时建议使用 css props object 模式,避免还需导入 css 函数:

const GreenText = {
  color: 'green',
}

若使用 css props 模式,还需要额外导入 css 函数(不推荐):

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

const GreenText = css`
  color: green;
`

第二种方案是从 babel 转译入手,直接使用配套插件即可。

使用 babel 转译插件
	yarn add -D @emotion/babel-preset-css-prop

之后在 babel 配置文件内添加此插件即可,由于 react 配置方案不统一,这里只介绍 cra 的配置方案:

// config-overrides.js

const { addBabelPreset } = require('customize-cra')

module.exports = {
  webpack: override(
    // emotion css props support
    addBabelPreset('@emotion/babel-preset-css-prop')
  )
}

有关 cra 方案的具体细节可参见:

《 react 不使用 eject 的配置方法( config-overrides 复现 vue 项目全部配置)》

总结

个人是比较推荐使用 babel 插件方案的,在开发环境默认转译,没有额外运行时掺杂到生产环境的不可控问题。

另外,不是很推荐使用 css props ,可以选择使用外链 css 文件或 @emotion/styled 的 styled-components 方案,都是很不错的选择。

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值