【问题标题】:Using useContext in React doesn't give me the expect data在 React 中使用 useContext 并没有给我期望的数据
【发布时间】:2020-06-24 21:55:16
【问题描述】:

我一直在关注一些 React Hooks 教程以使用 useContext

在父组件中,我创建了一个新的上下文,

export const Context = createContext({fakeData: 'fake'})

然后在其中一个子组件中,我尝试通过这样做来访问这些数据,

 console.log('fakeData1', useContext(Context))
 const context = useContext(Context)
 console.log('fakeData2', context)

然后我从父组件导入Context

在我的console.log 中,fakeData2 给了我未定义,但fakeData1 给了我

{$$typeof: Symbol(react.context), _calculateChangedBits: null, _currentValue: undefined, _currentValue2: {…}, _threadCount: 0, …}
$$typeof: Symbol(react.context)
Consumer: {$$typeof: Symbol(react.context), _context: {…}, _calculateChangedBits: null, …}
Provider:
$$typeof: Symbol(react.provider)
_context: {$$typeof: Symbol(react.context), _calculateChangedBits: null, _currentValue: {…}, _currentValue2: {…}, _threadCount: 0, …}
__proto__: Object
_calculateChangedBits: null
_currentRenderer: {}
_currentRenderer2: null
_currentValue: {fakeData: "fake"}
_currentValue2: {fakeData: "fake"}
_threadCount: 0
__proto__: Object

由于Context中有数据,我假设导入成功,但不知道为什么不能直接通过

const context = useContext(Context)
console.log('fakeData2', context)

我假设这个对象有一个名为 fakeData 的字段,但事实并非如此。

有什么帮助吗?

【问题讨论】:

  • const {fakeData} = useContext(Context) 能提供您想要的东西吗?
  • 这是我所期望的,但事实并非如此。 Context 对象没有名为 fakeData 的字段
  • 我注意到一个奇怪的行为,在createContext 中设置默认值会直接导致未定义的行为。尝试在提供程序的value 属性中对其进行初始化,并将createContext 的参数留空
  • 你是说像export const Context = createContext()一样清空Context的参数吗?这也没有奏效。它给了我同样的结果
  • 查看Codesandbox,它显示了一个工作示例。但是,如果您从 Context.Provider 组件中删除 value 属性,而是将默认值放在对 createContext 的调用中,则会导致您描述的未定义行为

标签: reactjs react-hooks react-context


【解决方案1】:

您可以通过上下文提供程序的value 属性在上下文中包含所需的默认值,而不是将它们传递给createContext

这就是我的意思:

// context.js
import { createContext } from "react";

export const Context = createContext(); // leave empty

// app.js
import React from "react";

import { Context } from "./context";

import Child from "./Child";

export default function App() {
  return (
    <Context.Provider value={{ fakeData: "test" }}> {/* pass default here */}
      <div className="App">
        <Child />
      </div>
    </Context.Provider>
  );
}

// Child.js
import React, { useContext } from "react";

import { Context } from "./context";

export default () => {
  const { fakeData } = useContext(Context);

  return <div>{fakeData}</div>;
};

这是一个Codesandbox,显示了上面的工作代码。

我不完全确定为什么原始方法不起作用,但我在自己的项目中也注意到了这一点。如果我找出确切原因,我会在这篇文章中添加一个编辑并给出解释。

【讨论】:

    【解决方案2】:

    正如React Docs中提到的:

    const MyContext = React.createContext(defaultValue);
    

    创建一个上下文对象。当 React 渲染一个订阅此 Context 对象的组件时,它将从树中最接近匹配的Provider 中读取当前上下文值。
    defaultValue 参数仅在组件在树中没有匹配的 Provider 时使用。这有助于在不包装组件的情况下单独测试组件。
    注意:undefined 作为Provider 值传递不会导致消费组件使用defaultValue

    因此,如果您在组件树中的组件上方渲染了Context.Provider,您将获得作为value 属性传递给它的值,而不是defaultValue

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-12-14
      • 2015-05-30
      • 2021-12-29
      • 2021-06-03
      • 2017-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多