鐵人賽
React
javascript
nodejs
vscode
鐵人賽第十二天,今天突然來了爆量的工作,一直忙到下班前,才有空檔;多虧通勤時規劃好內容,才能如行雲流水般的寫完文章。
我們在鐵人賽第七天-React Hook 起手式 ~ useState聊到useState
,定義好的state
及stateFunc
,我們可以使用props
往下傳遞;第二層、第三層應該都沒問題,那 第n層呢?
再思考一個,隨著前端設計的越來越複雜,compoent
定義在不同的JS
檔中,要如何搞定這問題呢?
為了解決這個問題,Context
登高一呼,號令大家說~「我把state、stateFunc及其他資源都放在這個global區域,你們儘管到這取用,別跑遠了!」
- Step1: 先透過
createContext
建立一個物件appStore
,這個物件通常建立在global
區,並透過export
將這個物件,提供給其他檔案import
使用。- Step2: 將剛剛建立的物件,以標籤語言包裝你的巢狀的Component**
- Step3: 在剛剛的標籤語言內,定義你要傳遞的值在標籤參數
value
,以Object
的形式包裝
// app.js
Import {createContext} from “React”
export const appStore
function TopComp(){
...
return(
<appStore.Provider value={{以Object的方式,放入你要傳遞的東西,ex: state, func, reducer...等}}>
<你的巢狀Components />
...
</appStore.Provider>
)
}
- Step4: 其他
JS
檔案,先透過import
將appStore
引入,接著,在function component
裡面,使用useContext
來存取上層定義的資源
import {useContext} from "react";
import {appStore} from "./app.js"
function CompA(){
const receivedGlobalData = useContext(appStore);
//=== 取得資料後,即可開始使用 ===
return(){...};
}
input
,使用者可以透過input
輸入文字,並顯示到一個<h1>
的文字區中。/src/components/ContextExample
/src/components/ContextExample/Message.js
,以建立顯示文字的元件// src/components/ContextExample/Message.js
import React, { createContext, useState } from "react"; //<-- (1)import createContext 準備使用
import Input from "./Input";
export const MsgStore = createContext(); //<--(2)在這裡建立一個context物件,並export出去,預備給其他component使用
export default function Message() {
const initTitle = "React Rookie's 30 days";
const [titleText, setTitleText] = useState(initTitle); //(3)<--useState設定
//(4)<MsgStore value={}>標籤符號,搭配value傳送物件
return (
<MsgStore.Provider
value={{ titleState: titleText, titleFunc: setTitleText }}
>
<h2>{titleText?titleText:setTitleText(initTitle)}</h2>
<Input />
</MsgStore.Provider>
);
}
/src/components/ContextExample/input.js
,建立輸入的元件//input.js
//(1) 定義一個<input>,提供輸入文字,
//(2) 呼叫useContext來取得app.js的global資料,
//(3) 並運用<input>的onChange的事件與app.js的title互動顯示
import React, { useContext } from "react"; //<--(1) 引用 useContext
import { MsgStore } from "./Message";
export default function Input() {
const { titleState, titleFunc } = useContext(MsgStore); //<--(2) 傳遞時用object, 因此接收時,也是以object的型態,接收titleState及titleFunc
console.log("get titleState from Context:" + titleState);
// (3)定義一個<input>,提供輸入文字
// 並運用<input>的onChange的事件與app.js的title互動顯示
return (
<>
<input onChange={(e) => titleFunc(e.target.value)}></input>
</>
);
}
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import Message from "./components/ContextExample/Message";
ReactDOM.render(
<Message/>,
document.getElementById('root')
);
初始畫面
在input
中打文字,可以看到,因為onChange
事件的運用,讓我們可以每打一個字,就更新在<h1>
的title處。
React Context
建立了一個共享空間,讓狀態能夠在components
之間交流,就像建立了一個中央控制台,統一操作、傳遞、交流;未來當我們的前端架構越來越複雜時,context
能幫我們省事不少,還不給個讚React
實力又往前邁進了一大步,今晚,就來點鼎泰豐的小籠包,給自己犒賞一番