react组件跨层级通信context

    科技2022-07-14  134

    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 ⾥。

    原文:视频讲解笔记

    Processed: 0.010, SQL: 8