如何使用useContext()设置值?

时间:2019-09-06 09:22:46

标签: reactjs gatsby

我正在尝试从嵌套子组件中在Context中设置状态,但是看不到我在上下文提供程序中创建的方法:

import React, { createContext, useState } from "react"

const Context = createContext({})

const Provider = ({ children }) => {
  const [value, setValue] = useState(undefined)

  return (
    <Context.Provider
      value={{
        value,
        loadValue: currentValue => {
          setValue(currentValue)
        },
      }}
    >
      {children}
    </Context.Provider>
  )
}

export default Context
export { Provider }

在子组件中,我尝试将其设置为:

import React, { useContext } from "react"
import Context from "../context/value.context"


const MyPage = ({ data }) => {
  const value = data.contentfulValue
  const { loadValue } = useContext(Context)

  loadValue(value)

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

export default MyPage

export const valueQuery = graphql`
  query valueBySlug($slug: String!) {
    contentfulValue(slug: { eq: $slug }) {
      ...
    }
  }
`

我得到的错误是TypeError: loadValue is not a function

2 个答案:

答案 0 :(得分:2)

虽然您没有提供完整的应用程序结构,

MyPage 不是Context.Provider的孩子时,您可能会遇到此类错误, 因此建议在创建上下文时添加一个初始值:

  

仅当组件在树中上方没有匹配的Provider时才使用defaultValue参数。这对于隔离测试组件而不进行包装很有帮助。注意:将undefined传递为Provider值不会导致使用组件使用defaultValue。

const Context = createContext({ value: undefined, loadValue: () => console.log('Default function') })

答案 1 :(得分:0)

我对您的代码做了一些更改

以命名上下文导出上下文,以便您可以使用它

import React, { createContext, useState } from "react"

export const Context = createContext({})

export default const Provider = ({ children }) => {
  const [value, setValue] = useState(undefined)

  return (
    <Context.Provider
      value={{
        value,
        loadValue: currentValue => {
          setValue(currentValue)
        },
      }}
    >
      {children}
    </Context.Provider>
  )
}

使用如下所示的静态上下文。

import React, { useContext } from "react"
import {Context} from "../context/value.context"


const MyPage = ({ data }) => {
  static contextType = Context
  const value = data.contentfulValue
  const { loadValue } = this.context

  loadValue(value)

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

export default MyPage

并记住在组件树的最顶部导入Provider,以便任何组件都可以使用它,

  <Provider>
      {/* <PageContent> */}
        <Navbar />
        <Forms />
      {/* </PageContent> */}
    </Provider>

如果仍然不起作用,请告诉我。