react组件跨层级通信context

React 中使⽤ Context 实现祖代组件向后代组件跨层级传值。 Vue中的 provide & inject 来源于 Context
 
Context API
 
React.createContext
 
创建⼀个 Context 对象。当 React 渲染⼀个订阅了这个Context 对象的组件,这个组件会从组件树中离⾃身最近的那个匹配Provider 中读取到当前的 context 值。
 
Context.Provider
 
Provider 接收⼀个 value 属性,传递给消费组件,允许消费组件订阅 context 的变化。⼀个 Provider 可以和多个消费组 件有对应关系。多个 Provider 也可以嵌套使⽤,⾥层的会覆 盖外层的数据。 当 Provider value 值发⽣变化时,它内部的所有消费组 件都会重新渲染。Provider 及其内部 consumer 组件都不受 制于 shouldComponentUpdate 函数,因此当 consumer 组 件在其祖先组件退出更新的情况下也能更新。
Class.contextType
 
挂载在 class 上的 contextType 属性会被重赋值为⼀个由 React.createContext() 创建的 Context 对象。这能让你 使⽤ this.context 来消费最近 Context 上的那个值。你可 以在任何⽣命周期中访问到它,包括 render 函数中。
 
Context.Consumer
 
这⾥, React 组件也可以订阅到 context 变更。这能让你在 函 数式组件 中完成订阅 context。 这个函数接收当前的 context 值,返回⼀个 React 节点。传 递给函数的 value 值等同于往上组件树离这个 context 最近 Provider 提供的 value 值。如果没有对应的
Provider value 参数等同于传递给 createContext() 的 defaultValue。
 
使⽤ Context
 
创建 Context => 获取 Provider Consumer => Provider 提供 值 => Consumer 消费值
 
范例:共享主题⾊
 
import React, {Component} from "react";
import {ThemeProvider} from "../themeContext";
import ContextTypePage from"./ContextTypePage";
import ConsumerPage from "./ConsumerPage";

class ContextPage extends Component {
 constructor(props) {
     super(props);
     this.state = {
         theme: {
             themeColor: "red"
         }
     };
 }
 changeColor = () => {
     const {themeColor} = this.state.theme;
     this.setState({
         theme: {
             themeColor: themeColor === "red" ? "green" : "red"
         }
     });
 };
 render() {
     const {theme} = this.state;
     return (
         <div className="App">
             {/* 组件跨层级通信 */}
             <button onClick= {this.changeColor}>change color</button>
             {/* 如果把这⾥的MyProvider注释掉,ContextTypePage和ConsumerPage⾥将取不到theme值,⽽取默认值pink */}
             <ThemeProvider value={theme}>
                 <ContextTypePage />
                 <ConsumerPage />
             </ThemeProvider>
         </div>
     );
 }
}
export default ContextPage;
//themeContext.js
 
import React from "react";
export const ThemeContext = React.createContext({themeColor: "pink"});
export const ThemeProvider = ThemeContext.Provider;
export const ThemeConsumer = ThemeContext.Consumer;
// pages/ContextTypePage.js
 
import React, {Component} from "react";
import {ThemeContext} from "../themeContext";
export default class ContextTypePage extends Component {
 static contextType = ThemeContext;
 render() {
     console.log("ContextTypePage",this.context); //sy-log
     const {themeColor} = this.context;
     return (
         <div className="border">
             <h3 className= {themeColor}>ContextTypePage</h3>
         </div>
     );
 }
}
// pages/ConsumerPage.js
 
import React, {Component} from "react";
import {ThemeConsumer} from "../themeContext";
export default class ConsumerPage extends Component {
 render() {
     return (
         <div className="border">
             <h3>ConsumerPage</h3>
             <ThemeConsumer>{ctx => <HandleTabBar{...ctx} />}</ThemeConsumer>
         </div>
     );
 }
}
function HandleTabBar({themeColor}) {
    console.log("themeColor", themeColor); //sylog
    return <div className={themeColor}>⽂本</div>;
}

注意:

       因为 context 会使⽤参考标识( reference identity )来决定 何时进⾏渲染,这⾥可能会有⼀些陷阱,当 provider 的⽗组 件进⾏重渲染时,可能会在 consumers 组件中触发意外的渲 染。
 

为了防⽌这种情况,将 value 状态提升到⽗节点的 state ⾥。

原文:视频讲解笔记

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值