【问题标题】:Difference Between Class.contextType and Context.Consumer with working exampleClass.contextType 和 Context.Consumer 之间的区别与工作示例
【发布时间】:2020-10-09 08:59:04
【问题描述】:

我正在尝试了解 React 上下文 API,并且正在阅读官方文档。如果有人能对以下几点提出更多说明,我将不胜感激,因为官方文档没有明确说明。

  1. contextType 和 Consumer 方法有什么区别 使用 Provider 提供的值?在什么情况下我们应该 使用哪种方法?
  2. Provider 在基于类的组件中公开的值可以是 由使用 useContext 的反应钩子组件使用?我有同样的 设置,我最终将 useContext 转换为 Context.Consumer。
  3. 我有一个非常简单的设置,其中我有一个提供者类 基于暴露一些状态值的组件。提供者 只有一个子组件,它也是一个消费者。当我使用 Context.Consumer 在孩子中获取值,一切 按预期工作。但是当我在孩子们中使用 contextType 组件,我看到一个空对象。

ContextProvider.js

import React from "react";
import {ContextConsumer} from "./ContextConsumer";
export const TestContext = React.createContext({
    count: 1,
    incrCount: (count)=>{
     console.log(`count value :- ${count}`)
     }
});

export class ContextProvider extends React.Component {
  incrCount = () => {
    this.setState({
      count: this.state.count + 1,
    });
  };

  state = {
    count: 5,
    incrCount: this.incrCount,
  };

  render() {
    return (
      <TestContext.Provider value={this.state}>
        <ContextConsumer />
      </TestContext.Provider>
    );
  }
}

ContextConsumer.js

import React from "react";
import { TestContext } from "./ContextProvider";

export class ContextConsumer extends React.Component {
    static contextType=TestContext

  componentDidMount() {
        const {count,incrCount}= this.context;
        console.log(`count:- ${(count)}`)
        console.log(`incrCount:- ${incrCount}`)
    }
  render() {


    return (
      <div>


        **// BELOW CODE IS WORKING AS EXPECTED**
        <TestContext.Consumer>
          {({ count, incrCount }) => (
            <button onClick={incrCount}>Count is {count}</button>
          )}
        </TestContext.Consumer>
      </div>
    );
  }
}

App.js

import {ContextProvider}  from "../../playground/ContextProvider";

const output = (
  <Provider store={reduxStore}>
    <ContextProvider />
  </Provider>
);

ReactDOM.render(output, document.getElementById("root"));

【问题讨论】:

标签: reactjs react-context


【解决方案1】:

contextType和Consumer方法消费Provider提供的值有什么区别?在什么情况下我们应该使用哪种方法?

static contextType 赋值是在 v16.6.0 中引入的,作为在渲染方法之外使用上下文的一种方式。 Consumer 和静态上下文之间的唯一区别是使用 contextType 允许您在渲染方法之外使用上下文

Provider在基于类的组件中暴露的值是否可以被使用useContext的react hook组件使用?

是的,来自 Provider 的上下文值也可以被 useContext 使用。但是,您只能在功能组件而不是类组件中使用 useContext,并且在 v16.8.0 或支持钩子的 react 之后也可以使用

P.S.您必须确保通过在消费者组件中导入提供程序不会导致循环依赖,反之亦然

【讨论】:

  • 我还参考了一篇在线文章,它说使用消费者是一种使用提供者值的传统和遗留方式。真的吗?如果是这种情况,我们是否只使用 contextType 但根据您的回复,我会不这么认为。 taniarascia.com/using-context-api-in-react。 “检索 Context 值的传统方法是将子组件包装在 Consumer 中。从那里,您可以将 value 属性作为 props 访问。您可能仍然会看到这一点,但它更像是访问 Context 的传统方式。 "
  • @ryan 上下文 api 已多次更改。最初我们需要定义 contextType,但也需要为我们使用 childContextTypes 的提供者。然后在 v16.3 中,react 引入了提供者消费者 api,它变得流行且简单,但有一个缺点是使用自定义来使用渲染函数之外的上下文,因此在 v16.6.0 中他们对其进行了改进并添加了静态 contextType 支持,以便我们可以在其他生命周期中也使用 contextType。然后随着钩子的出现,他们引入了 useContext 来在功能组件中使用上下文。
  • 因此,虽然 contextType 是传统方式,但它也是使用上下文的最新方式。
  • 我进行了更改并已将 componentDidMount 中的“console.log(this.context)”从渲染中移出,但我仍然看到这些值未定义。我在这里错过了什么?
  • 可能是循环依赖。在单独的文件中而不是在提供者中创建上下文
【解决方案2】:
  1. 静态 contextType 和 class.contextType
  2. 使用上下文
  3. context.Consumer

几乎相同,它们之间的区别在于(1)用于类组件和 useContext 是一个钩子,最好的是我们可以在一个功能组件中多次使用这个钩子。(3) 只能在 jsx 或 render(return) 中使用。(1) 和(2) 可以在 return 之外使用。

【讨论】:

    猜你喜欢
    • 2019-06-14
    • 1970-01-01
    • 2016-11-29
    • 2013-12-28
    • 2012-10-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-17
    相关资源
    最近更新 更多