React Hook 系列文
1. 從最基本的 Hook 開始 useState, useEffect
2. Memorized Hook- useMemo, useCallback
3. useRef
4. useContext
5. useReducer
6. useLayoutEffect

🔖 文章索引1. 前言 2. What’s Context Object? 3. What’s useContext? 4. 結論
一般來說,React 傳資料的方式都是一層一層把資料 props 傳到子層的

就算第二層 (Function Component)、第三層 (Button Group Compontn) 根本沒用到這資料,但為了傳到最底層 (button) ,每一層都還是必須要傳 props
寫久了會覺得麻煩,因為每一次都要這樣一層層傳資料下來 ( prop drilling),我們不知道到底哪一層真的使用到了,Refactor 時可能也會忘了清掉某一層 Props?! 那,是否有更好的方式呢?
那就是 Context
介紹
useContext
前一定要先來說Context
因為useContext
只是他之中Context.Consumer 的 sugar syntax
What’s Context Object?
Context Object 是被 createContext()
這個 API 所建立,裡面有兩個子元件
- Provider: 傳遞 value 這個值
- Consumer: 接收 value 這個值
const testContext = createContext(); const { Provider, Consumer } = testContext;
How to use the Provider?
我們會用
Context.Provider
包覆元件並傳遞value

我們使用 Context.Provider
來包覆元件,並傳遞一個 value
。我們先將資料透過 value
傳遞給 Provider
,Provider
再將資料傳給裡面的元件,如 FunctionComponent
及 ClassComponent
。
所以 FunctionComponent
跟 ClassContextComponent
都可以接收到 value
不需要再另外用 props 傳進去避免複雜的 nesting 結構,更神奇的是所以包在FunctionComponent
跟 ClassContextComponent
裡的所有子元件也同樣可以接收到 value
。
How to access our global data using Context()?
如何接收value
呢? 子元件只要包在 Context.Consumer
裡就可以接收到資料了
What’s useContext?
接收一個 context object(
React.createContext
的回傳值)並回傳該 context 目前的值。Context 目前的值是取決於由上層 component 距離最近的<MyContext.Provider>
的value
prop。
若 ButtonGroupComponent.js 用 useContext
這個 syntax sugar 改寫,會變更精減
不要忘記 useContext
的參數必需為 context object 自己:
- ✅ 正確:
useContext(MyContext)
- ❌ 錯誤:
useContext(MyContext.Consumer)
- ❌ 錯誤:
useContext(MyContext.Provider)
另外 Context 當然也可以再包 Context

value 不一定是 Primitive values 也可以是 object
value
也可以是比較複雜的物件或 array 的
useContext 跟 custom Hook 搭配起來會更加強大,例如可以寫一個 useTheme
把 useContext
包在裡面這樣就不用煩腦要在 function component 裡一直處理 Theme ,不過這就等到之後篇章再說囉
結論
並不是說可以用 useContext
去取代原本 props 的方法,而是根據使用情境不同選澤適合的資料傳遞方法。畢竟現在 context 有一個很大問題是每當它資料更新,底下所有子元件都會 re-render,所以不常變動的值 (例如 Theme)才適合用 useContext
,另外搭配 useMemo
一起使用更能節省效能 [延伸閱讀: The Problem with React’s Context API]
