React - Context 使用(共享对于一个组件树而言是 “全局” 的数据)
- 一. Context 概念理解
- 二. Context 使用
- 三. Context 组件传值实例
Context官网: https://zh-hans.reactjs.org/docs/context.html
一. Context 概念理解
Context
提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。- React的
context
就是一个全局变量,可以从根组件跨级别在React的组件中传递。 - 通常用于 祖组件 与 后代组件 之间通信。
二. Context 使用
-
创建一个 Context 对象
// 从 react 中引入 createContext import { createContext } from "react"; // 创建一个 Context 对象 const MyContext = createContext(defaultValue);
- 只有当组件所处的树中没有匹配到
Provider
时,其defaultValue
参数才会生效。 - 此默认值有助于在不使用
Provider
包装组件的情况下对组件进行测试。
- 只有当组件所处的树中没有匹配到
-
渲染子组件
- 每个
Context
对象都会返回一个Provider React
组件,它允许消费组件订阅context
的变化。 Provider
接收一个value
属性,传递给消费组件。一个Provider
可以和多个消费组件有对应关系。多个Provider
也可以嵌套使用,里层的会覆盖外层的数据。- 当
Provider
的value
值发生变化时,它内部的所有消费组件都会重新渲染。从Provider
到其内部consumer
组件(包括.contextType
和useContext
)的传播不受制于shouldComponentUpdate
函数,因此当consumer
组件在其祖先组件跳过更新的情况下也能更新。 - 通过新旧值检测来确定变化,使用了与
Object.is
相同的算法。
<MyContext.Provider value={value}> {/* 子组件 */} <component/> </MyContext.Provider>
- 渲染子组件时,外面包裹
xxxContext.Provider
- 通过
value
属性给后代组件传递数据
- 每个
-
后代组件读取数据
方法一:
Class.contextType
,仅适用于类组件。class MyClass extends React.Component { // 声明接收context,使用 static 这个类属性来初始化 contextType static contextType = MyContext; render() { // 读取context中的value数据 let value = this.context; /* 基于这个值进行渲染工作 */ } }
- 声明接收
context
,使用static
这个类属性来初始化contextType
。 - 通过
this.context
,读取context
中的value
数据。
方法二:
Context.Consumer
,函数组件与类组件都可以使用。<MyContext.Consumer> {value => /* 基于 context 值进行渲染*/} </MyContext.Consumer>
value
就是context
中的value
数据
- 声明接收
三. Context 组件传值实例
- 源码
import React, { Component } from "react"; import { createContext } from "react"; // 创建一个createContext对象 const CountContext = createContext(); // 从 Context 中获取 Provider, Consumer const { Provider, Consumer } = CountContext; export default class A extends Component { state = { count: 100, name: "tom", }; render() { const { name, count } = this.state; return ( <div> <h2>A组件</h2> <h4>数值为:{count}</h4> {/* 通过value属性给后代组件传递数据 */} <Provider value={{ name, count }}> <B /> </Provider> </div> ); } } class B extends Component { render() { return ( <div> <h2>B组件</h2> <C /> <D /> </div> ); } } class C extends Component { // 声明接收context static contextType = CountContext; render() { // 接收值 console.log(this.context); return ( <div> <h2>C组件</h2> <h4> 接收到的A组件数值为:{this.context.count},名字为:{this.context.name} </h4> </div> ); } } function D() { return ( <div> <h2>D组件</h2> <h4> <Consumer> {(value) => { // 接收值 console.log(value); return `接收到的A组件数值为:${value.count},名字为:${value.name}`; }} </Consumer> </h4> </div> ); }
- 实现效果