React中的Context应用场景分析


Posted in Javascript onJune 11, 2021

Context定义和目的

Context 提供了一种在组件之间共享数据的方式,而不必显式地通过组件树的逐层传递 props。

应用场景 哪些数据会需要共享?

Context 设计目的是为了共享那些对于一个组件树而言是**“全局”的数据**,例如当前认证的用户、主题或首选语言。

使用步骤

1. 创建并初始化Context

const MyContext = createContex(defaultValue);

创建一个 Context 对象。当 React 渲染一个订阅了这个 Context 对象的组件,这个组件会从组件树中离自身最近的那个匹配的 Provider 中读取到当前的 context 值。

2. 订阅Context

<MyContext.Provider value={/* 某个值 */}>

Provider 接收一个 value 属性,传递给消费组件。一个 Provider 可以和多个消费组件有对应关系。多个 Provider 也可以嵌套使用,里层的会覆盖外层的数据。

这里有两个相关的概念

  • Provider - Context提供者,或Context的订阅者。可以理解为通过Provider为其内部组件订阅了Context值的变动,一旦Context值有变化,就会触发内部组件重新渲染。
  • Comsumer - Context消费者(消费组件),或者叫Context使用者。即在Provider内部使用useContext()来使用或消费Context的组件。这些组件通过useContext()获取、使用Context的最新值。

3. 使用Conext

3.1 React组件中使用

const value = useContext(MyContext);

在消费组件中引用Context。value会从组件树中离自身最近的那个匹配的Provider中读取到当前的Context值。

3.2 纯函数式组件中使用

在纯函数式的组件中,可以使用Consumer来引用context的值。如果没有上层对应的Provider,value等同于传递给createContext()defaultValue.

<MyContext.Consumer>
  {value => /* 基于 context 值进行渲染*/}
</MyContext.Consumer>

4. Context的更新

4.1 自上而下更新Context

自上而下更新指的是更新Provider的value值。当 Provider 的 value 值发生变化时,它内部的所有消费组件内通过useContext获取到的值会自动更新,并触发重新渲染。

//App.js

// ....

export default function App() {
    //...
    
    // 
    const {contextValue, setContextValue} = React.useState(initialValue);

    // function to update the context value
    function updateContext(newValue) {
        // ...

        // 更新contextValue, ConsumerComponent1, ConsumerComponent2, ConsumerComponent3, ConsumerComponent11都会触发重新渲染。
        setContextValue(newValue)
    }

    ...
    return (
        <App>
            <MyContext.Provider value={contextValue}>
                <ConsumerComponent1>
                    <ConsumerComponent11>
    					// ....
                    </ComsumerComponent11>
                </ConsumerComponent1>

                <ConsumerComponent2 />
                <ConsumerComponent3 />
            </MyContext.Provider>
        </App>
    );
    
}

4.2 自下而上(从消费组件)更新Context

在某些情况下,需要在某个消费组件内更新context,并且适配到整个程序。比如通过应用程序的setting组件修改UI风格。 这时就需要通过回调将更新一层层传递到对应的Provider,更新Provide对应的value,从而触发所有相关消费组件的更新。

// app.js

export default function App() {
    ...
    const {contextValue, setContextValue} = React.useState(initialValue);

    // function to update the context value
    function updateContext(newValue) {
        // ...

        // 更新contextValue, ConsumerComponent1, ConsumerComponent2, ConsumerComponent3, ConsumerComponent11都会触发重新渲染。
        setContextValue(newValue)
    }

    ...
    return (
        <App>
            <MyContext.Provider value={contextValue}>
                <ConsumerComponent1>
                    <ConsumerComponent11 updateValue={updateContext}> // 通过回调形式的props, 在ConsumerComponent11中更新contextValue, 因为contextValue属于最顶层的Provider的值,所以也会触发ConsumerComponent1, ConsumerComponent2, ConsumerComponent3重新渲染。
                    </ComsumerComponent11>
                </ConsumerComponent1>

                <ConsumerComponent2 />
                <ConsumerComponent3 />
            </MyContext.Provider>
        </App>
    );
}

4.3 Provider嵌套

在一些情况下,可能会出现同一个Context的provider嵌套的情况,这时候可以理解为两个Context。不同的是,

...
const {contextValue, setContextValue} = React.useState(initialValue);

// function to update the context value
function updateContext(newValue) {
    // ...
    
    // 更新contextValue, ConsumerComponent1, ConsumerComponent2, ConsumerComponent3, ConsumerComponent11都会触发重新渲染。
    setContextValue(newValue)
}

...
return (
	<App>
        <MyContext.Provider value={contextValue}>
            <ConsumerComponent1>
                <ConsumerComponent11 />
            </ConsumerComponent1>

            <ConsumerComponent2>
                ...
                // 如果只希望更新ComsumerComponent21, ComsumerComponent22中的值
                
                const localContextValue = useContext(MyContext); // 从上一层Provider中获取当前值

				const {tempContextValue, setTempContextValue} = React.useState(localContextValue);

				function updateTempContext(newValue) {
                    // 这里更新以后只会触发ConsumerComponent21和ConsumerComponent22的重新渲染
                    setTempContextValue(newValue); 
                }

				// 这里新建Provider,在ConsumerComponent21和ConsumerComponent22之间共享数据。
                <MyContext.Provider value={tempValue}>
                    <ConsumerComponent21>
                    	// 在ConsumerComponent21中通过useContext(MyContext)订阅
                    	// 获取到的值为离自身最近的那个匹配的Provider中读取到的Context值,即tempValue
                    </ConsumerComponent21>
                    <ConsumerComponent22>
                    </ConsumerComponent22>
				</MyContext.Provider value={contextValue}>
            </ConsumerComponent2>
            <ConsumerComponent3 />
        </MyContext.Provider>
    </App>
);

官方文档

官方文档请参考下边的基础和高级教程。

Hook API 索引 ? React (reactjs.org)

Context ? React (reactjs.org)

以上就是React中的Context应用场景分析的详细内容,更多关于React中的Context的资料请关注三水点靠木其它相关文章!

Javascript 相关文章推荐
js 字符串操作函数
Jul 25 Javascript
一个用javascript写的select支持上下键、首字母筛选以及回车取值的功能
Sep 09 Javascript
清空上传控件input file的值
Jul 03 Javascript
理解Javascript_06_理解对象的创建过程
Oct 15 Javascript
js中indexof的用法详细解析
Dec 24 Javascript
javascript使用shift+click实现选择和反选checkbox的方法
May 04 Javascript
Javascript将数值转换为金额格式(分隔千分位和自动增加小数点)
Jun 22 Javascript
微信小程序 在Chrome浏览器上运行以及WebStorm的使用
Sep 27 Javascript
利用jQuery插件imgAreaSelect实现图片上传裁剪(放大缩小)
Dec 02 Javascript
jquery uploadify隐藏上传进度的实现方法
Feb 06 Javascript
Ajax高级笔记 JavaScript高级程序设计笔记
Jun 22 Javascript
Vue-cli3生成的Vue项目加载Mxgraph方法示例
May 31 Javascript
详解JVM系列之内存模型
使用Vue3+Vant组件实现App搜索历史记录功能(示例代码)
一文搞懂redux在react中的初步用法
Jun 09 #Javascript
深入详解JS函数的柯里化
Jun 09 #Javascript
javascript canvas实现雨滴效果
用JS实现飞机大战小游戏
Jun 09 #Javascript
原生JS实现飞机大战小游戏
You might like
php strtotime 函数UNIX时间戳
2009/01/14 PHP
深入php处理整数函数的详解
2013/06/09 PHP
IIS6.0中配置php服务全过程解析
2013/08/07 PHP
ThinkPHP中URL路径访问与模块控制器之间的关系
2014/08/23 PHP
PHP生成随机数的方法总结
2018/03/01 PHP
Yii2.0框架behaviors方法使用实例分析
2019/09/30 PHP
JavaScipt基本教程之JavaScript语言的基础
2008/01/16 Javascript
获取网站跟路径的javascript代码(站点及虚拟目录)
2009/10/20 Javascript
详解AngularJS的通信机制
2015/06/18 Javascript
在vue中安装使用vux的教程详解
2018/09/16 Javascript
[02:53]DOTA2英雄基础教程 山岭巨人小小
2013/12/09 DOTA
KMP算法精解及其Python版的代码示例
2016/06/01 Python
使用Python快速制作可视化报表的方法
2019/02/03 Python
pycharm访问mysql数据库的方法步骤
2019/06/18 Python
Python将string转换到float的实例方法
2019/07/29 Python
python3 tcp的粘包现象和解决办法解析
2019/12/09 Python
Python3 把一个列表按指定数目分成多个列表的方式
2019/12/25 Python
PyTorch 普通卷积和空洞卷积实例
2020/01/07 Python
使用Python实现牛顿法求极值
2020/02/10 Python
python实现批量修改文件名
2020/03/23 Python
Python操作Jira库常用方法解析
2020/04/10 Python
使用python无账号无限制获取企查查信息的实例代码
2020/04/17 Python
如何将PySpark导入Python的放实现(2种)
2020/04/26 Python
使用matlab 判断两个矩阵是否相等的实例
2020/05/11 Python
python中有帮助函数吗
2020/06/19 Python
pandas apply多线程实现代码
2020/08/17 Python
美国性感内衣店:Yandy
2018/06/12 全球购物
国际性能运动服装品牌:Dare 2b
2018/07/27 全球购物
说说在weblogic中开发消息Bean时的persistent与non-persisten的差别
2013/04/07 面试题
音乐学院硕士生的自我评价分享
2013/11/01 职场文书
学生会主席演讲稿
2014/04/25 职场文书
神农溪导游词
2015/02/11 职场文书
2015年员工工作总结范文
2015/04/08 职场文书
文员岗位职责范本
2015/04/16 职场文书
公司员工奖惩制度
2015/08/04 职场文书
2016大学迎新欢迎词
2015/09/29 职场文书