Open rccoder opened 6 years ago
妈妈,我再也不会滥用 Redux 了
context 是各种前后端框架中经常会用到的一个概念,著名 Node 框架 Koa 更是把 context 玩的尽兴。React 在很早之前就有 context 的概念,虽然是一个实验性质的 API,但 react-redux、react -router 等框架类库却把它玩了个够。
Koa
React 中爷爷和孙子,甚至是重孙之间传递值或者事件一直是个比较麻烦的事情,随着 Redux 等状态管理类库的出现,大家纷纷开始用这种框架去解决这种隔代传信息的问题,并且在或大或小的项目中都开始使用。
一回喜,二回忧,在前端视资源体积为金子的情况下 “滥用 Redux” 的情况越来越多。
React 新版本中的 context 终于要转正了,并且经过了重新的思考与沉淀,与之前 context 在设计哲学上不一样,但解决的却是同一个问题。这样,或许数据流真的不是很多的项目或许可以真的摆脱一下 Redux 等去试试自带的 Context 了。
本文将介绍新老 Context 的一些用法和自己的一些思考。
首先看一下最简单的 爷爷给孙子 传值的问题:
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 就能让这种信息自动的传递,不再让 中间辈 去担任消息传递人,做一些没太大意义的事。
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 的任何一个子孙(子组件)中访问。
GrandParent
getChildContext
text
同时,为了方便在各种生命周期中使用 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 包裹的里面的写法,不是普通的组件。
createContext
provider
consumer
虽然 context 可以是一个 Object,但还是避免不了业务逻辑中会出现多个 context 的问题,consumer 与 provider 一一对应的模式会造成花式嵌套地狱,可以使用伟大社区产生的 react-context-composer 对 context 进行 composer,源码也非常简单易懂。
不会,解决的终极问题不完全一样!
Redux 解决的是大型软件架构中数据流传输的问题;context 解决的是子孙之间方便数据交互的问题。有一定的相似性,但不属于同等性质。
前言
context 是各种前后端框架中经常会用到的一个概念,著名 Node 框架
Koa
更是把 context 玩的尽兴。React 在很早之前就有 context 的概念,虽然是一个实验性质的 API,但 react-redux、react -router 等框架类库却把它玩了个够。React 中爷爷和孙子,甚至是重孙之间传递值或者事件一直是个比较麻烦的事情,随着 Redux 等状态管理类库的出现,大家纷纷开始用这种框架去解决这种隔代传信息的问题,并且在或大或小的项目中都开始使用。
一回喜,二回忧,在前端视资源体积为金子的情况下 “滥用 Redux” 的情况越来越多。
React 新版本中的 context 终于要转正了,并且经过了重新的思考与沉淀,与之前 context 在设计哲学上不一样,但解决的却是同一个问题。这样,或许数据流真的不是很多的项目或许可以真的摆脱一下 Redux 等去试试自带的 Context 了。
本文将介绍新老 Context 的一些用法和自己的一些思考。
子孙传值问题
首先看一下最简单的 爷爷给孙子 传值的问题:
这几行代码中都是手动的让 text 一辈一辈 的往下传,如果是传给重孙的话还需要继续手动往下传。
利用 Context 就能让这种信息自动的传递,不再让 中间辈 去担任消息传递人,做一些没太大意义的事。
老 Context
在
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 之下上面的代码这样写:
新版 Context 用
createContext
去初始化一个 context,返回的对象中有provider
和consumer
方法。provider
是以外层容器的方式去包裹住 context 要作用的最外层组件(使用过 Redux 的同学对这点应该有种似曾相似的感觉),然后需要使用到 context 的时候需要用consumer
去包裹一下。需要注意的是consumer
包裹的里面的写法,不是普通的组件。虽然 context 可以是一个 Object,但还是避免不了业务逻辑中会出现多个 context 的问题,
consumer
与provider
一一对应的模式会造成花式嵌套地狱,可以使用伟大社区产生的 react-context-composer 对 context 进行 composer,源码也非常简单易懂。Context 会让 Redux 消失吗?
不会,解决的终极问题不完全一样!
Redux 解决的是大型软件架构中数据流传输的问题;context 解决的是子孙之间方便数据交互的问题。有一定的相似性,但不属于同等性质。
延伸阅读