useContext 返回未定义,即使它不应该是未定义的
useContext Returning Undefined Even Though It Shouldn't Be Undefined
我在 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]}
。因此,不应该使用具有两个值(即 show
和 setShow
)的数组来定义值吗?
知道为什么没有发生这种情况吗?我该如何解决?
谢谢。
更新
这是我调用 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
你应该给 PROVIDER'S CONSUMERS 打电话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>
)
}
我在 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]}
。因此,不应该使用具有两个值(即 show
和 setShow
)的数组来定义值吗?
知道为什么没有发生这种情况吗?我该如何解决?
谢谢。
更新
这是我调用 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
你应该给 PROVIDER'S CONSUMERS 打电话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>
)
}