React Context提供的函数在子组件调用未触发预期逻辑如何解决?
问题根源
你调用useAuth()的时机和位置错误:
Test组件执行时,首先就会调用useAuth(),此时组件还没有渲染返回的AuthProvider,且Test组件本身处于AuthProvider的层级之外,向上找不到对应的AuthContext.Provider,所以只会取到createContext时传入的默认值,也就是打印hey的login方法、始终为null的user。- 只有被
AuthProvider包裹的子组件内部调用useAuth,才能拿到Provider传入的自定义login、logout和user状态。
解决方案
有两种常用修正方式:
方式1:抽离内层业务组件,在Provider内部调用useAuth
修改pages/test.tsx代码如下:
// pages/test.tsx import {AuthProvider, useAuth} from "../contexts/auth"; // 业务逻辑放到被Provider包裹的子组件内 function TestContent() { const {user, login, logout} = useAuth(); console.log("user:", user); // 登录后会正确返回赋值后的user对象 return ( <div> <button onClick={login}> Log in </button> <button onClick={logout}> Log out </button> </div> ) } export default function Test() { // Test组件只负责挂载Provider,不调用Context return ( <AuthProvider> <TestContent /> </AuthProvider> ); }
方式2:把AuthProvider提到页面上层(Next.js场景推荐)
如果你需要全站共享登录状态,可以直接把AuthProvider放到pages/_app.tsx中包裹所有页面组件,这样所有页面内部都可以直接调用useAuth,不需要每个页面单独加Provider:
// pages/_app.tsx import type { AppProps } from 'next/app' import { AuthProvider } from '../contexts/auth' export default function MyApp({ Component, pageProps }: AppProps) { return ( <AuthProvider> <Component {...pageProps} /> </AuthProvider> ) }
修改后你原来的test.tsx可以简化为:
// pages/test.tsx import { useAuth } from "../contexts/auth"; export default function Test() { const {user, login, logout} = useAuth(); console.log("user:", user); return ( <div> <button onClick={login}> Log in </button> <button onClick={logout}> Log out </button> </div> ); }
内容的提问来源于stack exchange,提问作者Swix
相关产品推荐
相关产品推荐

