React类组件使用Context API报错:Cannot access 'MyContextApi' before initialization
错误原因
你的报错本质是循环依赖 + ES6 const 变量暂时性死区共同导致的:
Context.api.parent.js代码执行顺序是先导入ContextChildTwo,而ContextChildTwo反过来导入了父文件里的MyContextApi- 此时父文件还没执行到
export const MyContextApi = React.createContext({})这行代码,MyContextApi处于未初始化状态,const 声明的变量在初始化前访问就会抛出你遇到的报错。
解决方案
方案1(推荐):将Context抽离到独立文件(彻底解决循环依赖)
该方案符合React项目规范,也方便后续全局复用Context:
- 新建独立Context文件
MyContext.js,仅负责Context的创建:
// MyContext.js import React from 'react'; export const MyContextApi = React.createContext({});
- 修改
Context.api.parent.js,删掉原有的Context创建代码,改为从独立文件导入:
import React from 'react'; import { MyContextApi } from './MyContext'; import ContextChildOne from "./Context.api.childone"; import ContextChildTwo from "./Context.api.childtwo"; class ContextParent extends React.Component { render() { return ( <div> <p>context api parent tag</p> <MyContextApi.Provider value={{ concept: "Context API" }}> <ContextChildOne> <ContextChildTwo /> </ContextChildOne> </MyContextApi.Provider> </div> ); } } export default ContextParent;
- 修改
Context.api.childtwo.js,改为从独立Context文件导入,不要导入父组件文件:
import React from 'react'; import { MyContextApi } from './MyContext'; class ContextChildTwo extends React.Component { render() { return ( <div> <p>Child two of context</p> <p> THIS IS THE EXAMPLE OF CONTEXT API TO AVOID PROPS DRILLDOWN. THIS CONCEPT <span>{this.context.concept}</span> </p> </div> ); } } ContextChildTwo.contextType = MyContextApi; export default ContextChildTwo;
方案2(临时修复):调整父组件代码执行顺序
如果不想抽离文件,只需要把父组件中Context的创建逻辑移到子组件导入之前即可,保证子组件导入时Context已经完成初始化:
// Context.api.parent.js 调整顺序后的代码 import React from 'react'; // 先初始化Context export const MyContextApi = React.createContext({}); // 再导入依赖Context的子组件 import ContextChildOne from "./Context.api.childone"; import ContextChildTwo from "./Context.api.childtwo"; class ContextParent extends React.Component { // 原有代码保持不变 } export default ContextParent;
补充说明
如果之前你抽离到独立文件后仍报错,大概率是导入路径写错,或者仍有其他文件存在循环导入的情况,排查所有用到MyContextApi的文件,确认都是从独立Context文件导入即可。
内容的提问来源于stack exchange,提问作者Ram Kumar
相关产品推荐
相关产品推荐

