useContext Hook 是如何工作的
- 2019 年 10 月 5 日
- 筆記
所有這些新的React Hook之間都有一個宗旨:就是為了使函數組件像類組件一樣強大。
useContext
hook 與其它幾個有點不一樣,但它在特定場景下還是很有用的。
React 的 Context API
是一種在應用程式中深入傳遞數據的方法,而無需手動一個一個在多個父子孫之間傳遞 prop
。當咱們需要的只是傳遞數據時,它可以作為像Redux
這樣的工具的一個很好的替代。

使用 Context
,首先頂層先聲明 Provier
組件,並聲明 value
屬性,接著在後代組件中聲明 Consumer
組件,這個 Consumer
子組件,只能是唯一的一個函數,函數參數即是 Context
的負載。如果有多個 Context
,Provider
和 Consumer
任意的順序嵌套即可。
此外我們還可以針對任意一個 Context
使用 contextType
來簡化對這個 Context
負載的獲取。但在一個組件中,即使消費多個 Context
,contextType
也只能指向其中一個。

在 Hooks
環境中,依舊可以使用 Consumer
,但是 ContextType
作為類靜態成員肯定是用不了。Hooks 提供了 useContext
,不但解決了 Consumer
難用的問題同時也解決了 contextType
只能使用一個 context
的問題。
標準方式
使用 API的典型方法如下所示:
import React from "react"; import ReactDOM from "react-dom"; // 創建 Context const NumberContext = React.createContext(); // 它返回一個具有兩個值的對象 // { Provider, Consumer } function App() { // 使用 Provider 為所有子孫代提供 value 值 return ( <NumberContext.Provider value={42}> <div> <Display /> </div> </NumberContext.Provider> ); } function Display() { // 使用 Consumer 從上下文中獲取 value return ( <NumberContext.Consumer> {value => <div>The answer is {value}.</div>} </NumberContext.Consumer> ); } ReactDOM.render(<App />, document.querySelector("#root"));
可以 CodeSandbox上看看運行效果。
使用 useContext 方式
使用 useContext
hook 來重寫上面的示例
import React, { useContext } from 'react'; // ... function Display() { const value = useContext(NumberContext); return <div>The answer is {value}.</div>; }
調用useContext
,傳入從React.createContext
獲取的上下文對象。
唯一需要注意的是你必須將整個上下文對象傳遞給useContext
– 而不僅僅是Consumer
, 當然如果忘記了,React
會給出警告。
嵌套的 Consumers
你可能遇到這樣的情況,咱們的組件需要從多個父上下文中接收數據,從而導致這樣的程式碼
function HeaderBar() { return ( <CurrentUser.Consumer> {user => <Notifications.Consumer> {notifications => <header> Welcome back, {user.name}! You have {notifications.length} notifications. </header> } } </CurrentUser.Consumer> ); }
這種大量嵌套只是為了接收兩個值。下面是使用useContext
時的效果:
function HeaderBar() { const user = useContext(CurrentUser); const notifications = useContext(Notifications); return ( <header> Welcome back, {user.name}! You have {notifications.length} notifications. </header> ); }
總結
useContext
接收一個 context
對象(React.createContext
的返回值)並返回該 context
的當前值。當前的 context
值由上層組件中距離當前組件最近的 <CountContext.Provider>
的 value
prop 決定。
當組件上層最近的 <CountContext.Provider>
更新時,該 Hook 會觸發重渲染,並使用最新傳遞給 CountContext provider
的 context value
值。
別忘記 useContext
的參數必須是 context
對象本身:
- 正確: useContext(MyContext)
- 錯誤: useContext(MyContext.Consumer)
- 錯誤: useContext(MyContext.Provider)
調用了 useContext
的組件總會在 context
值變化時重新渲染。如果重渲染組件的開銷較大,你可以 通過使用 memoization
來優化。
程式碼部署後可能存在的BUG沒法實時知道,事後為了解決這些BUG,花了大量的時間進行log 調試,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug。
參考:
https://daveceddia.com/usecon…