首页 > 解决方案 > useContext 返回未定义,即使它不应该是未定义的

问题描述

我在 React 中创建了以下上下文:

import { useBoolean } from "@chakra-ui/react"
import { createContext, FC } from "react"

type useBooleanReturn = ReturnType<typeof useBoolean>

export const MobileContext = createContext<
  [show: useBooleanReturn[0], setShow: useBooleanReturn[1]] | undefined
>(undefined)

// --- PROVIDER
const MobileProvider: FC = ({ children }) => {
  const [show, setShow] = useBoolean()

  return (
    <MobileContext.Provider value={[show, setShow]}>
      {children}
    </MobileContext.Provider>
  )
}

export default MobileProvider

到目前为止一切都很好,但是当我尝试使用这个上下文时,事实证明正在传递的内容是undefined. 也就是说,在下面的代码value中是未定义的:

const value = React.useContext(MobileContext)

不过,我不知道为什么会这样,因为我useBoolean在设置上下文时使用了钩子——即这一行 const [show, setShow] = useBoolean()show然后,我将这一行传递setShow给我的上下文: value={[show, setShow]}. 因此,不应该使用具有两个值(即showsetShow)的数组来定义 value 吗?

知道为什么没有发生这种情况,我能做些什么来解决它?

谢谢。

更新 这是我打电话时的完整示例useContext

import * as React from "react"
import MobileProvider, { MobileContext } from "./context.mobile"

const Mobile = () => {
  const value = React.useContext(MobileContext)

  console.log("value:", value)
  ...

以上是我为测试目的所做的。这是我的代码实际上应该是这样的:

import * as React from "react"
import Base from "./base"

import Header from "./Header"
import Menu from "./Menu"
import Footer from "./Footer"


import MobileProvider, { MobileContext } from "./context.mobile"

const Mobile = () => {
  const [show, setShow] = React.useContext(MobileContext)

  return (
    <MobileProvider>
      <Base onClick={setShow.toggle} ref={ref} show={show}>
        <Header onClick={setShow.toggle} />
        <Menu />
        <Footer />
      </Base>
    </MobileProvider>
  )
}

export default Mobile

标签: reactjstypescriptreact-contextuse-context

解决方案


您应该呼吁提供者useContext的消费者。

换句话说,调用useContext( Mobile) 的组件必须是 的子组件MobileProvider

在您的情况下,它不是消费者,这不是 API 定义的方式,因此您将获得默认值 ( undefined),因为它是在上下文之外调用的。

const Mobile = () => {
  // NOT A CONSUMER
  const [show, setShow] = React.useContext(MobileContext)

  return (
    <MobileProvider>
      ...
    </MobileProvider>
  )
}

将组件移动到MobileProvider

<MobileProvider>
  <Mobile/>
</MobileProvider>

const Mobile = () => {
  // NOW A CONSUMER
  const [show, setShow] = React.useContext(MobileContext)

  return (
    <Base onClick={setShow.toggle} ref={ref} show={show}>
        ...
    </Base>
  )
}

推荐阅读