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 相关文章推荐
Javascript操纵Cookie实现购物车程序
Feb 15 Javascript
Auntion-TableSort国人写的一个javascript表格排序的东西
Nov 12 Javascript
javascript Demo模态窗口
Dec 06 Javascript
JSQL 基于客户端的成绩统计实现方法
May 05 Javascript
Js 时间间隔计算的函数(间隔天数)
Nov 15 Javascript
jQuery切换所有复选框选中状态的方法
Jul 02 Javascript
js生成随机数的方法实例
Oct 16 Javascript
JavaScript学习笔记之数组求和方法
Mar 23 Javascript
BootStrap实现带有增删改查功能的表格(DEMO详解)
Oct 26 Javascript
JS获取鼠标位置距浏览器窗口距离的方法示例
Apr 11 Javascript
详解项目升级到vue-cli3的正确姿势
Jan 28 Javascript
js+springMVC 提交数组数据到后台的实例
Sep 21 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获取ip对应地区和使用网络类型的方法
2015/03/11 PHP
PHP中类型转换 ,常量,系统常量,魔术常量的详解
2017/10/26 PHP
PHP实现基于图的深度优先遍历输出1,2,3...n的全排列功能
2017/11/10 PHP
PHP从零开始打造自己的MVC框架之入口文件实现方法详解
2019/06/03 PHP
PHP实现常用排序算法的方法
2020/02/05 PHP
微博@符号的用户名提示效果。(想@到谁?)
2010/11/05 Javascript
javascript的parseFloat()方法精度问题探讨
2013/11/26 Javascript
js处理自己不能定义二维数组的方法详解
2014/03/03 Javascript
封装好的js判断操作系统与浏览器代码分享
2015/01/09 Javascript
javascript实现完美拖拽效果
2015/05/06 Javascript
js生成随机数的方法实例
2015/10/16 Javascript
jQuery获取某天的农历日期并判断是否除夕或新年的方法
2016/03/01 Javascript
Ionic如何创建APP项目
2016/06/03 Javascript
由浅入深剖析Angular表单验证
2016/07/14 Javascript
jQuery实现动态控制页面元素的方法分析
2017/12/20 jQuery
使用javascript函数编写简单银行取钱存钱流程
2018/05/26 Javascript
vue.js父子组件通信动态绑定的实例
2018/09/28 Javascript
基于Vue实现的多条件筛选功能的详解(类似京东和淘宝功能)
2019/05/07 Javascript
通过angular CDK实现页面元素拖放的步骤详解
2020/07/01 Javascript
[11:57]《一刀刀一天》第十七期:TI中国军团加油!
2014/05/26 DOTA
[01:01:18]VP vs NIP 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
Python的净值数据接口调用示例分享
2016/03/15 Python
Python实现统计代码行的方法分析
2017/07/12 Python
详解分布式任务队列Celery使用说明
2018/11/29 Python
python在TXT文件中按照某一字符串取出该字符串所在的行方法
2018/12/10 Python
PyTorch的自适应池化Adaptive Pooling实例
2020/01/03 Python
python基于property()函数定义属性
2020/01/22 Python
Django单元测试中Fixtures的使用方法
2020/02/26 Python
Python实现爬取并分析电商评论
2020/06/19 Python
美国网上订购鲜花:FTD
2016/09/23 全球购物
Nixon手表英国官网:美国尼克松手表品牌
2020/02/10 全球购物
俄语专业职业生涯规划
2014/02/26 职场文书
党的群众路线教育实践活动个人对照检查材料范文
2014/09/25 职场文书
学校运动会开幕词
2016/03/03 职场文书
深入探讨opencv图像矫正算法实战
2021/05/21 Python
2021年国漫热度排行前十,完美世界上榜,第四是美国动画作品
2022/03/18 国漫