全新 React Context API
先講結論
Published in
5 min readApr 6, 2018
以更 functional 的方式來呈現 React Context,真的非常不錯!
什麼是 React Context?
在 React 的 application 中,Component 互相溝通的方式一律以 props 的方式傳遞,但你有沒有想過如果有一個 props 從上到下有超過 10 層 Component,但卻只有最上面與最下面的 Component 會用到,這樣每一層都要定義,不管是要加要拔都非常的麻煩,所以 React 提供了另一個傳遞資料的方法「Context」。
你什麼時候該使用 Context
在你的 React application 中,可能被視為「全域」的資料,像是當前使用者資料 (Current authenticated user)、主題 (Theme)、語系 (language) …等等,你都可以考慮作為 Context 來傳遞
以程式面來說,如果你有在使用 Redux ,私心覺得 Action 其實可以作為 Context 來傳遞,其實也是很方便的,如果你有不同意見,請告訴我!
舊的 Context API
// deliver need to define childContextTypes / getChildContextclass DeliverComponent extends Component {
getChildContext() {
return {color: "purple"};
} render() {
return (
<MidComponent />
)
}
}DeliverComponent.childContextTypes = {
color: PropTypes.string
};const MidComponent = (props) => <ReceiverComponent />;// receiver need to define contextTypes to get contextconst ReceiverComponent = (props, context) =>
<div style={{ color: context.color }}> Hello, this is receiver. </div>;ReceiverComponent.contextTypes = {
color: PropTypes.string
};
舊版 API 簡單講解
- 提供 Context 的 Component 要定義
childContextTypes
與getChildContext
才能把 Context 傳下去。 - 接收 Context 的 Component 要定義
contextTypes
,並從 context 接才能正確拿到資料。
只要有少定義或是型別錯誤,就會在瀏覽器的開發人員工具裡面噴 error 給你,定義嚴謹!而且可以在 React 開發工具中看到 context 的資料,debug 上也很方便!
新版 Context API
只要你是 React 16.3 以上的版本,就可以使用新的 Context API!
目前舊的 API 也一樣可以使用,還沒有被拿掉,但建議慢慢轉移到新的 API,以免未來被拔掉 (最好的例子是
React.createClass
)
import React, { Component, createContext } from 'react'const { Provider, Consumer } = createContext('color');const DeliverComponent = (props) =>
<Provider value="purple">
<MidComponent/>
</ Provider>;const MidComponent = (props) => <Receiver />;const Receiver = (props) =>
<Consumer>
{color =>
<div style={{ color }}> Hello, this is receiver.</div>
}
</Consumer>;
新版 API 簡單講解
- 依照定義不同可以利用
React.createContext
來定義各種不同的 Context - 提供 Context 的 Component 要用該 Context 的
Provider
把內容包起來,用 value 的屬性把資料傳遞下去。 - 接收 Context 的 Component 要用該 Context 的
Consumer
把內容包起來,用 inline arrow function 就可以接到 Context 的內容囉!
總結
- 新版可以依照不同的 Context 定義各種不同 Context ( 很方便 )
- 新版的提供了更 functional 的方式傳遞 Context,如果你有經歷過 React Router 升上 v4 的階段,也大概會有同樣的感覺!
- 雖然少了舊版的「直接」定義 Context 的型別,但新版要做到也不是不行 ( 利用 HOC 包住 Context Receiver,定義被包裝 Component 的 propTypes 也一樣可以做到!)
- 可以寫更多 functional Component 了( 撒花 🎉 )