react 【context在函数组件和class组件中的使用】
前言
在一个典型的 React 应用中,数据是通过 props 属性自上而下(由父及子)进行传递的,但这种做法对于某些类型的属性而言是极其繁琐的(例如:地区偏好,UI 主题),这些属性是应用程序中许多组件都需要的。Context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递 props。
可以访问的生命周期
class组件
在shouldComponentUpdate之后访问,constructor和getDeriverdStateFromProps中无法访问到
函数组件
函数组件通过hook访问
更新规则
当 Provider 的 value
值发生变化时,它内部的所有消费组件都会重新渲染。Provider 及其内部 consumer 组件都不受制于 shouldComponentUpdate
函数,因此当 consumer 组件在其祖先组件退出更新的情况下也能更新。
通过新旧值检测来确定变化,使用了与 Object.is
相同的算法。
涉及api
react.createContext:context函数
<Context.Provider>:组件元素,被包裹的组件可以及其子元素可以通过contextType消费context
Class.contextType:指定消费context,必须要是被<Context.Provider>包裹的元素
Context.Consumer:指定消费context,和Class.contextType作用一致,区别是此方法适用于函数组件。 与Context.Provider不同的是,Context.Provider可以嵌套使用,而Context.Consumer的children必须是一个函数组件
ps:函数组件推荐使用hook useContext,此方法或许在后续版本会被移除.
Context.displayName:定义context在devtools中的别名配合调试工具使用
涉及hook
useContext
案例代码
class
//创建一个context const MyContext = react.createContext("init"); //祖先组件 const ancestor = () => { return ( <div> <h2>ancestor</h2> <div> <MyContext.Provider value={"context value"}> //包裹子组件 <Son /> </MyContext.Provider> </div> </div> ); }; //子组件 const Son = () => { return ( <div> <h2>son</h2> <div> <Grandson /> //孙组件 </div> </div> ); }; //孙组件 class Grandson extends react.Component { //注入context 在class组件中,必须要为static属性contextType,设置通过react.createContext()创建的context对象,才能使用this.context,不然this.context的值会为一个{} static contextType = MyContext; componentDidMount() { console.log(this.context); //context value } render() { return ( <div> <h2>grandson</h2> <div> <span>获取的context值:</span> </div> </div> ); } }
函组件
const Son = (props: any) => { const context: any = useContext(MyContext); //通过hook useContext指定消费Context, console.log("son", context); // return ( <div> {/* 其他输出 */} </div> ); };