React 中的新旧 Context 简单对比

原文地址:https://github.com/rccoder/blog/issues/30html

妈妈,我不再会滥用 Redux 了前端

前言

context 是各类先后端框架中常常会用到的一个概念,著名 Node 框架 Koa 更是把 context 玩的尽兴。React 在很早以前就有 context 的概念,虽然是一个实验性质的 API,但 react-redux、react -router 等框架类库却把它玩了个够。react

React 中爷爷和孙子,甚至是重孙之间传递值或者事件一直是个比较麻烦的事情,随着 Redux 等状态管理类库的出现,你们纷纷开始用这种框架去解决这种隔代传信息的问题,而且在或大或小的项目中都开始使用。git

一回喜,二回忧,在前端视资源体积为金子的状况下 “滥用 Redux” 的状况愈来愈多。github

React 新版本中的 context 终于要转正了,而且通过了从新的思考与沉淀,与以前 context 在设计哲学上不同,但解决的倒是同一个问题。这样,或许数据流真的不是不少的项目或许能够真的摆脱一下 Redux 等去试试自带的 Context 了。redux

本文将介绍新老 Context 的一些用法和本身的一些思考。后端

子孙传值问题

首先看一下最简单的 爷爷给孙子 传值的问题:api

class Children extends React.Component {
  render() {
    return (
      <div>{ this.props.text }</div>
      )
    }
}

class Parent extends React.Component {
  render() {
    return (
      <Children text="this.props.text"/>
     )
  }
}

class GrandParent extends React.Component {
  render() {
    return (
      <Parent text="Hi, my baby"/>
    )
  }
}
复制代码

这几行代码中都是手动的让 text 一辈一辈 的往下传,若是是传给重孙的话还须要继续手动往下传。架构

利用 Context 就能让这种信息自动的传递,再也不让 中间辈 去担任消息传递人,作一些没太大意义的事。composer

老 Context

const PropTypes = require('prop-types');

class Children extends React.Component {
  static contextTypes = {
    text: PropTypes.string
  }
  render() {
    return (
      <div>{ this.context.text }</div>
    )
  }
}

class Parent extends React.Component {
  render() {
    return (
      <Children/>
    )
  }
}

class GrandParent extends React.Component {
  static childContextTypes = {
    text: PropTypes.string,
  }
  getChildContext() {
    return {
      text: 'Hi, my baby'
    }
  }
  render() {
    return (
      <Parent text="Hi, my baby" /> ) } } 复制代码

GrandParent 上经过 getChildContext 给 context 对象添加了 text 的属性,这个属性能够在 GrandParent 的任何一个子孙(子组件)中访问。

同时,为了方便在各类生命周期中使用 context,部分生命周期都给 context 留了接口,具体能够参考 Referencing Context in Lifecycle Methods

新 Context

老式的 context 和依靠中间辈一层层去传递数据相比确实是酷酷的,但总感受不 React。或许这也是为何以前一直不建议使用的缘由吧。

同时还有一个比较🤢的 context 更新问题,更多能够参考 How to safely use React context

在 React 16.3 中 新版本的 Context 出炉了,感兴趣的能够参考 rfc提案

新版 context 之下上面的代码这样写:

const AppContext = React.createContext();


class Children extends React.Component {
  render() {
    return (
      <AppContext.Consumer>
        {
          context => {
            return (
              <div>{context.text}</div>
            )
          }
        }
       </AppContext.Consumer>
     )
   }
}

class Parent extends React.Component {
  render() {
    return (
      <Children />
    )
  }
}

class GrandParent extends React.Component {
  render() {
    return (
      <AppContext.Provider
        value={{
          text: 'Hi, my baby'
        }}
       >
         <Parent />
       </AppContext.Provider>
     )
   }
}
复制代码

新版 Context 用 createContext 去初始化一个 context,返回的对象中有 providerconsumer 方法。provider 是之外层容器的方式去包裹住 context 要做用的最外层组件(使用过 Redux 的同窗对这点应该有种似曾类似的感受),而后须要使用到 context 的时候须要用 consumer 去包裹一下。须要注意的是 consumer 包裹的里面的写法,不是普通的组件。

虽然 context 能够是一个 Object,但仍是避免不了业务逻辑中会出现多个 context 的问题,consumerprovider 一一对应的模式会形成花式嵌套地狱,可使用伟大社区产生的 react-context-composer 对 context 进行 composer,源码也很是简单易懂。

Context 会让 Redux 消失吗?

不会,解决的终极问题不彻底同样!

Redux 解决的是大型软件架构中数据流传输的问题;context 解决的是子孙之间方便数据交互的问题。有必定的类似性,但不属于同等性质。

延伸阅读

题外

文章内容第一时间更新地址为:https://github.com/rccoder/blog/issues/30。为保证看到的是最新的,交流 & 阅读优先点击 这里

相关文章
相关标签/搜索