原文地址: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。爲保證看到的是最新的,交流 & 閱讀優先點擊 這裏。