React 17中'jsx'必须在作用域内错误的解决方法及疑问
问题原因与解决方案解析
1. ESLint报错“'jsx' must be in scope when using JSX”的原因
你添加了Emotion的JSX编译指令/** @jsx jsx */,这个指令告诉编译器:不要用默认的React.createElement处理JSX,而是用名为jsx的函数。
ESLint的react/react-in-jsx-scope规则原本是检查React是否在作用域(适配React 17之前的版本),但当检测到自定义JSX pragma时,它会转而检查pragma中指定的变量(这里是jsx)是否存在于当前作用域。你只导入了React的几个钩子,没导入Emotion的jsx函数,所以ESLint抛出错误。
2. 关闭ESLint规则后编译报错“jsx is not defined”的原因
关闭react/react-in-jsx-scope只是让ESLint停止检查,但编译阶段(Babel或React的JSX转换器)仍然会按照你指定的pragma去寻找jsx函数。因为你从未从@emotion/react导入这个函数,所以编译时找不到变量jsx,直接报错。
3. 换成import React from 'react'后问题解决的原因
当你移除Emotion的自定义pragma(或者隐式使用默认的React JSX处理逻辑),加上显式导入React后:
- React 17+的自动JSX转换机制,即使不导入React也能处理JSX,但显式导入
React后,编译器会回退到用React.createElement处理JSX,此时不需要额外的jsx变量,编译自然通过。 - ESLint的
react/react-in-jsx-scope规则检测到React在作用域,不会再抛出错误。 - 如果你同时在用Emotion的样式功能(比如
cssprop),此时可能依赖@emotion/babel-plugin这类工具自动处理样式注入,所以不会影响样式生效。
正确的解决方式(保留Emotion的JSX pragma)
如果你想继续使用Emotion的自定义JSX处理(比如更好地支持css prop、样式隔离),应该补充导入Emotion的jsx函数:
/** @jsx jsx */ import { createContext, useContext, useState } from 'react'; import { jsx } from '@emotion/react'; // 必须导入这个jsx函数 // 你的Context组件代码 const MyContext = createContext(); function MyContextProvider({ children }) { const [state, setState] = useState({}); return ( <MyContext.Provider value={{ state, setState }}> {children} </MyContext.Provider> ); }
同时,建议在ESLint配置中调整规则,适配Emotion的pragma:
// eslintrc.js module.exports = { rules: { 'react/react-in-jsx-scope': 'off', // 如果使用eslint-plugin-emotion,还可以开启对应的规则 '@emotion/jsx-import': 'error' } };
内容的提问来源于stack exchange,提问作者meez
相关产品推荐
相关产品推荐

