React使用useContext报错:Cannot read properties of undefined (reading 'state')
React useContext报错:Cannot read properties of undefined (reading 'state')
问题说明
使用useContext时触发错误:Cannot read properties of undefined (reading 'state'),错误触发位置在About.js文件中,怀疑是新版本React的API变化导致问题。
相关代码
App.js
import './App.css'; import {BrowserRouter as Router,Routes ,Route,} from "react-router-dom"; import Navbar from './components/Navbar'; import { Home } from './components/Home'; import { About } from './components/About'; import NoteState from './context/notes/NoteState'; function App() { return ( <div className="main"> <NoteState> <About /> </NoteState> <Router> <Navbar /> {/* <LoadingBar color='#f11946' height={3} progress={progress} /> */} <Routes> <Route exact path="/" element={<Home />}></Route> <Route exact path="/about" element={<About />}></Route> </Routes> </Router> </div> ); } export default App;
About.js
import React, {useContext, useEffect} from 'react' //import NoteState from '../context/notes/NoteState'; import NoteContext from '../context/notes/noteContext'; export const About = () => { const a = useContext(NoteContext) useEffect(() => { a.update(); // eslint-disable-next-line }, []) return ( <div>my name is {a.state.name}</div> ) }
noteContext.js
import { createContext } from "react"; const NoteContext = createContext(); export default NoteContext;
noteState.js
import NoteContext from "./noteContext"; import { useState } from "react"; const NoteState = (props)=> { const s1 = { "name": "Harry", "class": "5b" } const [state, setState] = useState(s1); const update = ()=>{ setTimeout(() => { setState({ "name": "Larry", "class": "10b" }) }, 1000); } return ( <NoteContext.Provider value={{state:state, update:update}}> {props.children} </NoteContext.Provider> ) } export default NoteState;
解决方案
问题核心是路由中渲染的About组件没有被NoteState的Context Provider包裹:
- 当前App.js里仅单独包裹了一个未关联路由的
<About />,但路由匹配时渲染的<About />不在NoteContext的Provider范围内。 - 由于创建Context时没有传入默认值(
createContext()),useContext会返回undefined,导致访问a.state.name时报错。
修改方式
将整个Router组件放入NoteState内部,让所有路由组件都能访问Context:
import './App.css'; import {BrowserRouter as Router,Routes ,Route,} from "react-router-dom"; import Navbar from './components/Navbar'; import { Home } from './components/Home'; import { About } from './components/About'; import NoteState from './context/notes/NoteState'; function App() { return ( <div className="main"> <NoteState> <Router> <Navbar /> {/* <LoadingBar color='#f11946' height={3} progress={progress} /> */} <Routes> <Route exact path="/" element={<Home />}></Route> <Route exact path="/about" element={<About />}></Route> </Routes> </Router> </NoteState> </div> ); } export default App;
可选方案
如果不需要全局包裹Context,也可以单独在路由的element中包裹About:
<Route exact path="/about" element={<NoteState><About /></NoteState>}></Route>
内容的提问来源于stack exchange,提问作者Abdullah Khalid
相关产品推荐
相关产品推荐

