使用React Hook无法在另一个组件中读取Context值
在React开发中使用Context API共享状态时,出现异常:FooterComponent组件无法读取AuthContext中的number值,抛出TypeError: Cannot read properties of undefined (reading 'number')错误。
相关代码
AuthContext.js
import React, { createContext, useContext, useState } from "react"; export const AuthContext = createContext(); export const useAuth = () => useContext(AuthContext) export default function AuthProvider({ children }) { const [number, setNumber] = useState(0) setInterval( () => setNumber(number+1), 10000 ) const valueToBeShared = {number} return ( <AuthContext.Provider value={ valueToBeShared }> {children} </AuthContext.Provider> ); };
FooterComponent.jsx
import { useContext } from "react"; import { AuthContext } from "./AuthContext"; function FooterComponent() { const authContext = useContext(AuthContext) console.log(`Footer component - ${authContext.number}`); return ( <div> Your Footer </div> ) } export default FooterComponent
报错信息
TypeError: Cannot read properties of undefined (reading 'number')
at FooterComponent (:64:49)
at renderWithHooks (:12163:28)
at mountIndeterminateComponent (:15575:23)
at beginWork (:16592:24)
at beginWork$1 (:20001:24)
at performUnitOfWork (:19458:22)
at workLoopSync (:19392:15)
at renderRootSync (:19370:17)
at recoverFromConcurrentError (:18968:30)
已执行的排查操作
- 添加了
React.createContext(); - 检查了
createContext(number);的传参
解决方案
确保FooterComponent在AuthProvider的子树中
这是报错的核心原因:如果组件没有被对应的Context Provider包裹,useContext(AuthContext)会返回createContext()的默认值(这里未传默认值,所以是undefined),自然无法读取number属性。需在应用根组件或FooterComponent的父组件层级中,用AuthProvider包裹相关组件,示例:
import AuthProvider from './AuthContext'; import FooterComponent from './FooterComponent'; function App() { return ( <AuthProvider> {/* 其他组件 */} <FooterComponent /> </AuthProvider> ); }修复setInterval的闭包问题
当前代码中setInterval的回调使用number+1更新状态,会因闭包导致number始终取初始渲染时的0值,最终每次更新都是0+1=1,无法实现递增效果。需改用函数式更新:setInterval( () => setNumber(prevNumber => prevNumber + 1), 10000 )可选:给createContext设置默认值
可以给createContext传入默认值,避免未被Provider包裹时直接报错,示例:export const AuthContext = createContext({ number: 0 });
内容的提问来源于stack exchange,提问作者Aaa A

