###### tags: `ReactJS` # React Context API - 給予元件 Context 不限定於根元素,在其 Context 下的子元件皆可取得該 Store - Redux 只能建立一個全域的 Store # Context API vs Redux - 當擁有大量全域變數時,會造成 APP 非常龐大 - 解法: 多做一層元件包裹,將 State 相關的抽出去那層即可,利用 Props下傳即可 - 最底下有範例 # Notes - 仍需要 react-redux / redux-thunk / redux 套件? # 選擇是否使用 Context API 需要關注的點 - [建議可以看看此段解說](http://bit.ly/2NlBvx4) - Context 可用於更新頻率低的 State - 更新頻率高的 State,React 會需要往上查找而耗費多餘的效能 # Links - [React Context API 教學 (Class Base 版)](http://bit.ly/2ClfAQA) - [React Context API 教學 (Function Base 版)](http://bit.ly/2JZ8vsX) - [React Context & Hooks (Net Ninja)](http://bit.ly/2NMGupx) - [Functional Base 使用 useContext 取得 Context 內容](http://bit.ly/2ChhOAm) - [引入 Redux Reducer 寫法(useContext & useReducer)](http://bit.ly/34zxECv) # 範例 # 建立 context 檔案 - context/example-context.js ```javascript= import React from 'react' // 等同建立 Store // 必須 export 才可給予 元件使用,在此可以設置預設值 export default React.createContext({ userList: [], // 建議在這裡補上用到那些 Function & 變數 (autocomplete才會支援) addUser: () => {} }) ``` # 父元件引用 ```javascript= // 父元件中引用 此 Context // 給予名稱大駝峰 (我們要將其視為元件來使用) import ExampleContext from '/context/example-context' import React from 'react' export default function parent() { // 亦可搬進元件撰寫預設值 const [userList, setUserList] = useState([]) // 設定 State const addUser = user => { setTimeout(() => { this.setState({ userList: [1,2,3] }) }, 1000) } // value 為雙層 傳遞物件下去給子元件,Function 亦可傳給子元件使用 return ( <ExampleContext.Provider value={{ userList, addUser, }}> {/* 給予 value 動態值,當數值變動,子元件會做重新渲染 */} {/* 包裹元件原本的內容 */} </ExampleContext.Provider> ) } ``` # 子元件使用 Context - 法1: 使用 ExampleContext.Consumer 包裹 - 法2: 使 contextType (限定於 ClassBase & 16.6+版本) - 法3: 利用 useContext 取代 Consumer (Function Base) ```javascript= // 子元件中使用 import ExampleContext from '/context/example-context' import React from 'react' // 子元件為 Consumer export default function child() { return ( <ExampleContext.Consumer> {/* 原始內容 可以使用 context 參數 */} {context => ( <h1>{context.test}</h1> )} </ExampleContext.Consumer> ) } ``` ```javascript= // 即可使用 this.context 取得 context 值 // 即不需要使用 ExampleContext.Consumer 包裹 static contextType = ExampleContext ``` # 全域 Store 層抽出 - context/GlobalState.js ```javascript= // 將 GlobalState 層從 APP 抽出 // 記得更改 Import import React from 'react' export default function GlobalState(props) { // 將全域的 State、Function 等,抽出放在此元件中 const [userList, setUserList] = useState([]) const addUser = user => {} return ( <GlobalState.Provider value={{ userList, addUser }}> {props.children} </GlobalState.Provider> ) } // 回到 App.js 將其內容以 GlobalState 包裹即可 <GlobalState></GlobalState> ``` # 使用 useContext 取得 Context 內容 * Functional Base ```javascript= import React, {useContext} from 'react' import ExampleContext from '/context/example-context' export function Index () { const msg = useContext(ExampleContext); return ( <div> <h1>{msg}</h1> </div> ) } ``` # useReducer (待補) - [useReducer 介紹](http://bit.ly/2NmpZSe) - 概念與 Redux 類似,加上 Ducks (將 ActionType、Action、Reducer寫在同一支 ) - 可以將 Function 抽出成另一支檔案,export Reducer ```javascript= ```
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up