Why
過往,我們為了避免 props
過度傳遞(Prop Drilling)往下太多層, 或是需要跨多個元件,共享資料。
我們往往會使用 React Context 來共享資料。
How
Show me the code
Codesandbox Demo
useContext
。過往是透過 Context Consumer 這個元件取得共享狀態,
假設我們想建立一個有主題( Light / Dark theme )樣式的全域共享狀態,實作方法如下
<ThemeProvider>
元件,提供給整個 App 使用主題們的實際樣式
const themes = {
light: {
foreground: "#000000",
background: "#eeeeee"
},
dark: {
foreground: "#ffffff",
background: "#222222"
}
};
建立、定義 Context 需要儲存的資料與預設值
export const ThemeContext = React.createContext({
theme: themes.dark,
toggleTheme: () => {}
});
建立 Provider 元件,與實作切換 theme 的狀態,並且提供這個 theme 給 Provider。
const ThemeProvider = ({ children }) => {
const [dark, setDark] = useState(true);
const toggleTheme = () => setDark(!dark);
const theme = dark ? themes.dark : themes.light;
const defaultValue = {
toggleTheme,
theme
};
return (
<ThemeContext.Provider value={defaultValue}>
{children}
</ThemeContext.Provider>
);
};
export default ThemeProvider;
在 index.js 內用<ThemeProvider>
元件,把整個 App 包裹起來,供應全站分享主題樣式。
<ThemeProvider>
<App />
</ThemeProvider>
在 App.js 中,套用全站樣式,透過 useContext
取得我們 theme 的共享資料。useContext(ThemeContext)
。 hook 中需要帶入一個參數,也就是指我們需要取得哪個共享資料的 Context (我們可以有許多不同的 Context )
const { theme } = useContext(ThemeContext);
return (
<div
className="App"
style={{
color: theme.foreground,
backgroundColor: theme.background
}}
>
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<ThemeButton />
</div>
);
在需要呼叫 toggleTheme
的地方,也使用 useContext(ThemeContext)
const ThemeButton = () => {
const { toggleTheme } = useContext(ThemeContext);
return <button onClick={toggleTheme}>切換深夜模式</button>;
};
如此我們便完成了 useContext 的練習。
Codesandbox Demo
注意:我們的 <App>
、 <ThemeButton>
都沒有透過 props
來取得 theme 跟 toggleTheme 這兩個狀態。
以下是個在 index.js 當中常見到的 pattern,我們將不同性質的狀態分散在不同的 Provider
,實現關注點分離 (Separation of concerns),使我們的程式碼比較好維護。
<ThemeProvider>
<SnackbarProvider>
<AuthProvider>
<ApiProvider>
<App />
</ApiProvider>
</AuthProvider>
</SnackbarProvider>
</ThemeProvider>
Toggle theme using React Hooks
Reactjs
透過 React CreateContext 搭配 React useContext 與 useReducer 來做 Global State Manager
Prop Drilling