原文地址: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
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 和依靠中间辈一层层去传递数据相比确实是酷酷的,但总感受不 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,返回的对象中有 provider
和 consumer
方法。provider
是之外层容器的方式去包裹住 context 要做用的最外层组件(使用过 Redux 的同窗对这点应该有种似曾类似的感受),而后须要使用到 context 的时候须要用 consumer
去包裹一下。须要注意的是 consumer
包裹的里面的写法,不是普通的组件。
虽然 context 能够是一个 Object,但仍是避免不了业务逻辑中会出现多个 context 的问题,consumer
与 provider
一一对应的模式会形成花式嵌套地狱,可使用伟大社区产生的 react-context-composer 对 context 进行 composer,源码也很是简单易懂。
不会,解决的终极问题不彻底同样!
Redux 解决的是大型软件架构中数据流传输的问题;context 解决的是子孙之间方便数据交互的问题。有必定的类似性,但不属于同等性质。
文章内容第一时间更新地址为:https://github.com/rccoder/blog/issues/30。为保证看到的是最新的,交流 & 阅读优先点击 这里。