Class.contextType 和 Context.Consumer 之间的区别与工作示例

Posted

技术标签:

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

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

    contextType 和 Consumer 方法有什么区别 使用 Provider 提供的值?在什么情况下我们应该 使用哪种方法? Provider 在基于类的组件中公开的值可以是 由使用 useContext 的反应钩子组件使用?我有同样的 设置,我最终将 useContext 转换为 Context.Consumer。 我有一个非常简单的设置,其中我有一个提供者类 基于暴露一些状态值的组件。提供者 只有一个子组件,它也是一个消费者。当我使用 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"));

【问题讨论】:

我认为您使用的是 v16.3.0 - v16​​.6.0 之间的 react 版本。 contextType 支持是在 16.6.0 中引入的。请查看此帖子***.com/questions/49870098/… 是的,我目前在 16.13.1。但是上下文页面上没有与版本支持相关的信息reactjs.org/docs/context.html @ryna,文档显示了最新版本的API,具体API介绍需要查看发行说明::reactjs.org/blog/2018/10/23/react-v-16-6.html 【参考方案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】:
    静态 contextType 和 class.contextType 使用上下文 context.Consumer

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

【讨论】:

以上是关于Class.contextType 和 Context.Consumer 之间的区别与工作示例的主要内容,如果未能解决你的问题,请参考以下文章

sh Findhttp://www.cyberciti.biz/faq/unix-linux-finding-files-by-content/

sh Findhttp://www.cyberciti.biz/faq/unix-linux-finding-files-by-content/

spring配置问题:严重: Error configuring application listener of class org.springframework.web.context.Conte

iOSCGContextSaveGState: invalid context 0x0. If you want to see the backtrace, please set CG_CONTE(代

在 Spring+Tomcat 上使用 JSF 2.2.9 会导致 java.lang.NoClassDefFoundError: javax/enterprise/context/spi/Conte

AAPT: error: resource drawable/soil_backgroud_content3 (aka cn.bloghut:drawable/soil_backgroud_conte