context

定义: Context提供了一种方式,能够让数据在组件树中传递,而不必一级一级手动传递。

API : createContext(defaultValue?)。

使用方法:

首先要引入createContext

import React, { Component, createContext } from 'react';

然后创建一个Context

const BatteryContext = createContext();

然后用BatteryContext.Provider包裹组件并且传递属性值。

<BatteryContext.Provider value={60}>
<Middle />  //子组件
</BatteryContext.Provider>

为了方便看出效果,将定义一个子组件和一个孙组件。然后不通过子组件,孙组件直接取值。

import React, { Component, createContext } from 'react';

const BatteryContext = createContext();

//声明一个孙组件
class Leaf extends Component {
render() {
return ( )
}
} //声明一个子组件
class Middle extends Component {
render() {
return <Leaf />
}
} class App extends Component {
render(){
return (
<BatteryContext.Provider value={60}>
<Middle />
</BatteryContext.Provider>
);
}
} export default App;

孙组件需要BatteryContext.Consumer来接收值,Consumer里面不能直接渲染其他组件,而是要声明一个函数。函数的参数就是context的值。

class Leaf extends Component {
render() {
return (
<BatteryContext.Consumer>
{
battery => <h1>Battery : {battery}</h1>
}
</BatteryContext.Consumer>
)
}
}

效果图;

这样没通过Middle组件来传递值,但是Leaf组件能通过context来获得属性。这就是context的基本用法。

context不但能跨层级来传递属性值,还能在属性值发生变化的时候重渲染Consumer下面的元素,举个例子:
 
在state中定义battery并赋值
state = {
battery: 60
}
然后做一个按钮,每次点击的时候都要battery减一。  代码:
render() {
const { battery } = this.state;
return (
<BatteryContext.Provider value={battery}>
<button
type="button"
onClick={() => this.setState({ battery: battery - 1 })}
>
减减
</button>
<Middle />
</BatteryContext.Provider>
);
}
全部代码:
import React, { Component, createContext } from 'react';

const BatteryContext = createContext();

//声明一个孙组件
class Leaf extends Component {
render() {
return (
<BatteryContext.Consumer>
{
battery => <h1>Battery : {battery}</h1>
}
</BatteryContext.Consumer>
)
}
} //声明一个子组件
class Middle extends Component {
render() {
return <Leaf />
}
} class App extends Component {
state = {
battery: 60
}
render() {
const { battery } = this.state;
return (
<BatteryContext.Provider value={battery}>
<button
type="button"
onClick={() => this.setState({ battery: battery - 1 })}
>
减减
</button>
<Middle />
</BatteryContext.Provider>
);
} } export default App;

效果图:

这样每次点击都会使battery得数值发生变化,从而重渲染Consumer下面的元素。

如果有多个Context该怎么做呢?我们在创建一个 Context
const OnLineContext = createContext();
如果有多个context变量的话,只需要把Privider嵌套进来即可,顺序不重要。接下来声明online的Provider了。
class App extends Component {
state = {
battery: 60,
online: false
}
render() {
const { battery, online } = this.state;
return (
<BatteryContext.Provider value={battery}>
<OnLineContext.Provider value={online} >
<button
type="button"
onClick={() => this.setState({ battery: battery - 1 })}
>
减减
</button>
<button
type="button"
onClick={() => this.setState({ online: !online })}
>
Switch
</button>
<Middle />
</OnLineContext.Provider>
</BatteryContext.Provider>
);
}
与Provider类似。Consumer也需要嵌套,顺序不重要。只要Consumer需要声明函数,所以要注意语法。
class Leaf extends Component {
render() {
return (
<BatteryContext.Consumer>
{
battery => (
<OnLineContext.Consumer>
{
online => <h1>Battery : {battery} , Online : {online.toString()}</h1>
}
</OnLineContext.Consumer>
)
}
</BatteryContext.Consumer>
)
}
}

全部代码:

import React, { Component, createContext } from 'react';

const BatteryContext = createContext();
const OnLineContext = createContext(); //声明一个孙组件
class Leaf extends Component {
render() {
return (
//与Provider类似。Consumer也需要嵌套,顺序不重要。只要Consumer需要声明函数,所以要注意语法。
<BatteryContext.Consumer>
{
battery => (
<OnLineContext.Consumer>
{
online => <h1>Battery : {battery} , Online : {online.toString()}</h1>
}
</OnLineContext.Consumer>
)
}
</BatteryContext.Consumer>
)
}
} //声明一个子组件
class Middle extends Component {
render() {
return <Leaf />
}
} class App extends Component {
state = {
battery: 60,
online: false
}
render() {
const { battery, online } = this.state;
//接下来声明online的Provider了。如果有多个context变量的话,只需要把Privider嵌套进来即可,顺序不重要。
return (
<BatteryContext.Provider value={battery}>
<OnLineContext.Provider value={online} >
<button
type="button"
onClick={() => this.setState({ battery: battery - 1 })}
>
减减
</button>
<button
type="button"
onClick={() => this.setState({ online: !online })}
>
Switch
</button>
<Middle />
</OnLineContext.Provider>
</BatteryContext.Provider>
);
} } export default App;

效果图:

还有一个问题 , 如果Consumer向上找不到对应的Provider怎么办?
 
其实即使找不到也不会报错,而是显示为空。那怎么设置默认值呢?
 
那上面的demo举例 ,刚才我们设置的battery为60。如果Consumer向上找不到BatteryContext.Provider的值,我们可以这样设置默认值:
const BatteryContext = createContext(30);
这样BatteryContext.Consumer向上找不到值,就会取默认值30。
context不仅仅只是可以传数值,也可以传函数。大家可以试试看。
最后再提示一下大家,不要滥用context,不然会影响组件的独立性。 如果一个组件中只使用一个Context的话,就可以使用contextType代替Consumer。详见https://www.cnblogs.com/littleSpill/p/11221817.html
 
 
 

React的Context的使用方法简介的更多相关文章

  1. React的contextType的使用方法简介

    上一篇介绍了Context的使用方法.但是Context会让组件变得不纯粹,因为依赖了全局变量.所以这决定了Context一般不会大规模的使用.所以一般在一个组件中使用一个Context就好. 由于C ...

  2. iOS中常用的四种数据持久化方法简介

    iOS中常用的四种数据持久化方法简介 iOS中的数据持久化方式,基本上有以下四种:属性列表.对象归档.SQLite3和Core Data 1.属性列表涉及到的主要类:NSUserDefaults,一般 ...

  3. 手写一个React-Redux,玩转React的Context API

    上一篇文章我们手写了一个Redux,但是单纯的Redux只是一个状态机,是没有UI呈现的,所以一般我们使用的时候都会配合一个UI库,比如在React中使用Redux就会用到React-Redux这个库 ...

  4. 网络神器Greasemonkey(油猴子)使用方法简介+脚本分享【转载】

    推荐下,觉得这个方法有用, 今天艾薇百科来介绍一下功能强大的Greasemonkey,俗称"油猴子",Greasemonkey可以自由定制网页,实现你想要的各种功能.堪称" ...

  5. Redis Cluster搭建方法简介22211111

    Redis Cluster搭建方法简介 (2013-05-29 17:08:57) 转载▼       Redis Cluster即Redis的分布式版本,将是Redis继支持Lua脚本之后的又一重磅 ...

  6. Monte Carlo方法简介(转载)

    Monte Carlo方法简介(转载)       今天向大家介绍一下我现在主要做的这个东东. Monte Carlo方法又称为随机抽样技巧或统计实验方法,属于计算数学的一个分支,它是在上世纪四十年代 ...

  7. C#——Marshal.StructureToPtr方法简介

    目录 MarshalStructureToPtr方法简介 功能及位置 语法 参数说明 异常 备注 举例 本博客(http://blog.csdn.net/livelylittlefish)贴出作者(三 ...

  8. Fatal error: Using $this when not in object context in 解决方法

    Fatal error: Using $this when not in object context in 解决方法 粗心造成的错误 $this 只存在于下面情况 $obj = new object ...

  9. TabBarController创建及使用方法简介

    TabBarController创建及使用方法简介 大致讲解一下TabBarController的创建过程: 首先,我们需要一些视图,如创建UIControllerView类型的view1,view2 ...

随机推荐

  1. 让您的应用兼容 Android Oreo

    不知不觉Android Oreo已经发布几个月时间了,你的应用开始使用最新平台了吗?在应用迁移过程中是否遇到了一些棘手问题?你的Android应用兼容Oreo如何呢? 我们应该都知道,每一次重大升级, ...

  2. css的圣杯布局

    圣杯布局和双飞翼布局实现的效果是一样的. 代码解析: 1.四个section,container,main,left,right.其中那个container为父容器. 2.main,left,righ ...

  3. MySQL 其它基本操作

    索引 所谓索引,就是类似于书的目录,目的也类似,都是为了提高检索速度.ALTER TABLE <表名> ADD INDEX <索引名(列名)>;或者CREATE INDEX & ...

  4. Elasticsearch教程(二)java集成Elasticsearch

    1.添加maven <!--tika抽取文件内容 --> <dependency> <groupId>org.apache.tika</groupId> ...

  5. 避免用户重复点击按钮(使用Enable:=False,消息繁忙时会有堵塞的问题,只能改用Sleep)

    // 现象描述://    用户点击按钮后程序开始繁忙工作,这时候用户不知道是否成功,就继续点几次//    采用Enalbe = false ... = true的方式发现还会触发点击,分析原因如下 ...

  6. Oracle 裁掉北京研发团队,相应职位撤回美国(收购了NetSuite,LogFire,Dyn)

    根据中国日报报道,2017年1月14日上午9点09分,甲骨文北京研发团队的同事收到了来自BU老大的一封邮件.邮件上提及,由于市场变化,甲骨文开始整合各研发中心资源公司在云计算方向发力,文末单独提出了甲 ...

  7. Qt优雅地结束线程(两种方法都是用Mutex锁住bool变量进行修改,然后由bool变量控制耗时动作的退出,即正常退出)

    如果一个线程运行完成,就会结束.可很多情况并非这么简单,由于某种特殊原因,当线程还未执行完时,我们就想中止它.不恰当的中止往往会引起一些未知错误.比如:当关闭主界面的时候,很有可能次线程正在运行,这时 ...

  8. iOS密码框实现(二)取消确定按钮

    由于将确定按钮去掉了,所以需要重新修改下代码,当输入第四个数字时,自动进入房间.   iOS 密码框效果图:     实现方式:   首先声明一个block初始化方法,因为这只是个框框,并不需要处理网 ...

  9. 事务 ( 进程 ID 60) 与另一个进程被死锁在锁资源上,并且已被选作死锁牺牲品

    Select * FROM [TableName] With(NoLock) .....

  10. 设计模式之单例模式的几种写法——java

    对于设计模式的使用场景和好处,之前有介绍一篇,今天主要是单例模式的编写方式,直接看代码吧 单例模式之饿汉模式,不会懒加载.线程安全 /** * @Author wangtao * @Descripti ...