React的Context API

更新日期: 2020-02-28阅读: 2k标签: api

前言

上下文(Context) 提供了在组件之间共享这些值的方法,而不必在树的每个层级显式传递一个 prop 。

一般情况下,在你没有绝对把握用好和必须的场景下,是不推荐使用的。

但是我们依然间接的使用着它,比如许多官方依赖在使用,如:react-redux, mobx-react,react-router。我们需要它功能的时候,更多是靠第三方依赖库就能实现,而不是自己手动写context。但是,依然需要理解它,对用它的一些依赖库源码理解很有帮助。

import React, { Component } from 'react';

class Grandpa extends Component {
    state = {
        info: 'GrandPa组件的信息'
    }
    render() {
        return (
            <div>
                <Father info={this.state.info}/>
            </div>
        );
    }
}

class Father extends Component {
    render() {
        return (
            <div>
                <Son info={this.props.info}/>
            </div>
        );
    }
}

class Son extends Component {
    render() {
        return (
            <div>
                我是Son组件,拿到信息为:{this.props.info}
            </div>
        );
    }
}

export default Grandpa;

最后页面输出:

我是Son组件,拿到信息为:GrandPa组件的信息

我们会发现这样的缺点是一层一层传值,如果有更多层级和更多数据的话,会让代码看起来很不整洁,如果中间哪个组件忘了传值基本就完了;而且Father组件也并没有用到info值,只是将值传给Son组件。

如果使用context,就能帮我们解决这个层级不停传值的问题。

context有旧版和新版之分,以React v16.3.0版本划分。


旧版Context api

我们先来说下旧版context API

将代码改成如下:

import React, { Component } from 'react';
import PropTypes from 'prop-types';

class Grandpa extends Component {
    state = {
        info: 'GrandPa组件的信息'
    }
    getChildContext () {
        return { info: this.state.info }
    }
    render() {
        return (
            <div>
                <Father/>
            </div>
        );
    }
}
// 声明Context对象属性
Grandpa.childContextTypes  = {
    info: PropTypes.string
}

class Father extends Component {
    render() {
        return (
            <div>
                <Son/>
            </div>
        );
    }
}

class Son extends Component {
    render() {
        return (
            <div>
                我是Son组件,拿到信息为:{this.context.info}
            </div>
        );
    }
}
// 根据约定好的参数类型声明
Son.contextTypes  = {
    info: PropTypes.string
}
export default Grandpa;

对PropTypes类型检查,还可以写成下面这种写法

class Grandpa extends Component {
    static childContextTypes = {
        info: PropTypes.string
    }
    state = {
        info: 'GrandPa组件的信息'
    }
    getChildContext () {
        return { info: this.state.info }
    }
    render() {
        return (
            <div>
                <Father/>
            </div>
        );
    }
}

在需要传出去的context值和需要接收context值都要进行类型检查判断。

正常用这个api可能没什么问题,但如果中间哪个组件用到shouldComponentUpdate方法的话,就很可能出现问题。

三个组件的层级关系如下

<GrandPa>
    <Father>
        <Son/>
    </Father>
</GrandPa>

如果在GrandPa组件设置按钮点击可以更新info的值,即通过this.setState({info: '改变值'})方法
更新 Context:
那么

  • GrandPa组件通过 setState 设置新的 Context 值同时触发子组件重新render。
  • Father组件重新render。
  • Son组件重新render,并拿到更新后的Context。

假如在Father组件添加函数

shouldComponentUpdate () {
    return false
}

由于Father并不依赖任何值,所以我们默认让它无需重新render。但是,这会导致Son组件也不会重新render,即无法获取到最新的 Context 值。

这样的不确定性对于目标组件来说是完全不可控的,也就是说目标组件无法保证自己每一次都可以接收到更新后的 Context 值。这是旧版API存在的一个大问题。

而新版API解决了这个问题,我们来看下新版API怎么写的


新版Context API

新版Context 新增了 creactContext() 方法用来创建一个context对象。这个对象包含两个组件,一个是 Provider(生产者),另一个是 Consumer(消费者)。
  1. Provider 和 Consumer 必须来自同一个Context对象,即一个由 React.createContext()创建的Context对象。
  2. React.createContext()方法接收一个参数做默认值,当 Consumer 外层没有对应的 Provider 时就会使用该默认值。
  3. Provider 组件使用Object.is方法判断prop值是否发生改变,当prop的值改变时,其内部组件树中对应的 Consumer 组件会接收到新值并重新渲染。此过程不受 shouldComponentUpdete 方法的影响。
  4. Consumer 组件接收一个函数作为 children prop 并利用该函数的返回值生成组件树的模式被称为 Render Props 模式。

用法

  1. 首先创建一个context对象
React.createContext 方法用于创建一个 Context 对象。该对象包含 Provider 和 Consumer两个属性,分别为两个 React 组件。
const InfoContext = React.createContext('');
  1. 使用Provider组件生成一个context
class Grandpa extends Component {
    state = {
        info: 'GrandPa组件的信息'
    }
    render() {
        return (
            <InfoContext.Provider value={{ info: this.state.info }}>
                <Father/>
            </InfoContext.Provider>
        );
    }
}
  1. 使用Consumer组件获取context对象的值
class Son extends Component {
    render() {
        return (
            <InfoContext.Consumer>
            {
                value => {
                    return <div>我是Son组件,拿到信息为:{value.info}</div>
                }
            }
            </InfoContext.Consumer>
        );
    }
}

链接: https://fly63.com/article/detial/8799

浏览器中的图像识别 API

在 Native 开发中,Android 和 IOS 平台都在系统层面直接提供给了应用开发识别图像的一些能力,比如对于二维码/条形码的识别,Android 可以使用 barcode API 、 iOS 可以使用 CIQRCodeFeature API 。

JavaScript的API设计原则

Js的API设计原则总共包含了七个大块。系卤煮自己总结的一些经验和教训。本篇博文同时也参考了其他一些文章,相关地址会在后面贴出来。很难做到详尽充实,如果有好的建议或者不对的地方,还望不吝赐教斧正。

适合写api接口文档的管理工具有哪些?

现在越来越流行前后端分离开发,使用ajax交互。所以api接口文档就变的十分有意义了,目前市场有哪些比较优秀的接口文档管理工具呢?比如:MinDoc,eoLinker,apizza,RAML,Swagger等等

前后端分离,如何防止api接口被恶意调用或攻击

无论网站,还是App目前基本都是基于api接口模式的开发,那么api的安全就尤为重要了。目前攻击最常见的就是“短信轰炸机”,由于短信接口验证是App,网站检验用户手机号最真实的途径,使用短信验证码在提供便利的同时,也成了呗恶意攻击的对象,那么如何才能防止被恶意调用呢?

JSON API免费接口_ 免费的天气预报、地图、IP、手机信息查询、翻译、新闻等api接口

整理提供最新的各种免费JSON接口,其中有部分需要用JSONP调用。方面前端同学的学习或在网站中的使用,包括:免费的天气预报、地图、IP、手机信息查询、翻译、新闻等api接口

什么是RESTful API?

要弄清楚什么是RESTful API,首先要弄清楚什么是REST。REST -- REpresentational State Transfer,英语的直译就是“表现层状态转移”。如果看这个概念,估计没几个人能明白是什么意思。

认识 Fetch API

Fetch API 已经作为现代浏览器中异步网络请求的标准方法,其使用 Promise 作为基本构造要素。Fetch 在主流浏览器中都有很好的支持,除了IE。

用一个通俗的例子讲清楚API

随着移动互联网的发展, 基于互联网的应用正变得越来越普及,在这个过程中,更多的平台将自身的资源开放给开发者来调用。对外提供的API 调用使得平台之间的内容关联性更强,同时这些开放的平台也为用户、开发者和中小网站带来了更大的价值。

docker提供api访问

环境centos,添加deamon.json后,dockerd命令可以启动docker,这时请求 127.0.0.1:2375 可以正常访问,使用systemctl无法启动docker的情况.无法启动docker:查看当前的docker配置

构建API的最佳编程语言是什么?

你是否正在设计第一个Web应用程序?也许你过去已经建立了一些,但是目前也正在寻找语言的变化以提高你的技能,或尝试新的东西。有了所有信息,就很难决定为下一个产品或项目选择哪种编程语言。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!