React 上下文提供程序未设置值

React Context Provider not setting value

我正在尝试开始使用 React 上下文挂钩,但我似乎遇到了一个我不明白的问题。

我已经定义了一个用户上下文,它只是一个表示“你好用户”的字符串:

import { useContext, createContext } from "react"

export const UserContext = createContext<string | null>(null)

export interface IAuth {
  children: React.ReactNode;
}

const Auth: React.FC<IAuth> = (props) => {

  return(
    <UserContext.Provider value={"hello user"}>
      {props.children}
    </UserContext.Provider>
  )
}

export default Auth

然后我尝试访问是这样的:

const Dash: NextPage<dashPageProps> = (props) => {

  const contextMsg = useContext(UserContext)

  const submitForm = () => {
    console.log("logout")
  }

  return (
    <Auth>
    <div className="w-screen">
      <div className='text-xl'>
        Dashboard
      </div>
      <h1>{contextMsg}</h1>
      <button className='bg-gray-400 border-2 border-gray-600 w-fit mt-5' onClick={submitForm} >Log out</button>
    </div>
    </Auth>
  )
}

export default Dash

但是即使我在使用 UserContext.Provider 时设置了一个值,也没有打印出任何内容。如果我在创建上下文时指定一个值,但当我通过提供者设置它时没有指定,它将有一个值。

我做错了什么?

您的 Auth 在组件中被调用,但您在 Auth 使用之前调用了 useContext,这意味着您的上下文 API 尚未初始化

在通常的组件中,您可以使用像

这样的组件包装器来初始化它们
<Context.Provider>
  <YourComponent/> // you call `useContext` in `YourComponent`
</Context.Provider>

但在Next.js中,尤其是在page-level组件下,由于代码整洁问题,构建多个ContextAPI并不是一个好方法

我建议您将 Auth 移动到 _app.tsx,如下所示,这将帮助您在所有 page-level 组件渲染之前初始化上下文 API

export default function MyApp(props: AppProps) {
  const { Component, pageProps } = props

  return (
    <React.Fragment>
      <Auth>
        <Component {...pageProps} />
      </Auth>
    </React.Fragment>
  )
}

Dash.tsx

const Dash: NextPage<dashPageProps> = (props) => {

  const contextMsg = useContext(UserContext)

  const submitForm = () => {
    console.log("logout")
  }

  return (
    <div className="w-screen">
      <div className='text-xl'>
        Dashboard
      </div>
      <h1>{contextMsg}</h1>
      <button className='bg-gray-400 border-2 border-gray-600 w-fit mt-5' onClick={submitForm} >Log out</button>
    </div>
  )
}

export default Dash

您不能 useContext 在其 Provider 之外。

您需要将 Auth 组件向上移动一个级别,使其包围 Dash 以便使用 const contextMsg = useContext(UserContext)

最终你的 React 组件树应该是这样的:

<Auth>
  <Dash />
</Auth>