iT邦幫忙

2022 iThome 鐵人賽

DAY 15
0

昨天我們用useState、useEffect、react-bootstrap完成了todolist程式,不過在寫程式的過程中,會發現我們傳遞的props隨著功能的增加越變越多,而且有些props甚至傳了好幾層的component,這樣在管理state和props上略顯麻煩,尤其是當我們要做更大型專案時,更需要一個有效管理state和props的工具。這種時候,就可以使用useContext來處理。

useContext簡介

有時候,我們會需要props傳遞好幾層的component,即使中間的component不需要,為了傳到底層也不得不傳進去,這樣很麻煩,一旦傳遞的props數量變多,還容易忘記或出錯。

useContext可以妥善解決這個問題。
useContext是可以讓props跨元件共享的一個hooks,透過useContext,需要跨層傳遞的props可以直接在component內取用,而不需要一直傳遞一直傳遞。

使用useContext

那要如何使用useContext呢?大體來說,要先創建一個context object,再用context provider包裹並傳遞,要用的時候則是用useContext取值使用。

context object

首先要先有一個context object,這個context object會先用createContext()這個api建立。由於會在useContext中使用到,因此一般會將其export出去:

export const myContext = createContext();

建立後的context object有兩個子元件:

  1. Provider:提供要傳入其他component的props
  2. Consumer:接收傳入component的props

以往多是使用Consumer來接收props,由於hooks的出現,useContext的方式也很常用。

在建立context object時,也可以定義預設值,當取用的component上方沒有Provider時,會取用到預設值。

export const myContext = createContext("default value");

context provider

建立好context object後,就需要使用Provider把需要的props傳出去:

const ContextProvider = ({children}) => {
    const theme = {
        light: {
            background:"white",
            color: "black"
        },
        dark: {
            background: "black",
            color: "white"
        }
    }
    // 需要傳入theme.dark
    return (
        <myContext.Provider value={theme.dark}>
            {children}
        </myContext.Provider>
    )
}

其中,children是要包裹進Provider中的子元件,由於Provider可以傳遞props進子元件,即使是巢狀元件也可以,因此通常會將它包在需用的最外層。

要注意的是,Provider外面取用不到傳入的value,只能取用到createContext時設定的預設值。

useContext

接著要在component中取用context object的value(props),要使用useContext()的函式來取值。在useContext()中傳入之前建立的context object:

const Component3 = () => {
    const theme = useContext(myContext);
    return (
        <div style={theme}>
            <p>Hello, world</p>
        </div>
    )
}

這樣就能取到值,並將其傳入到需要使用的地方。如上面這個component3,透過context的方式取用到最上層的theme.dark,並將裡面的樣式object傳入style裡,就能顯示出設定好的樣式。

有一點要注意:useContext只會取用離自己最近Provider的值,如果有兩個相同context object的Provider,只會取最近這個component的Provider

useContext的使用時機

useContext相當好用,但有個缺點,就是每當context object的值變動(例如state更新),底下的所有component都會re-render一遍。因此,useContext比較適合用在不常變動的值上,避免不斷re-render,影響效能。
此外,當今天有許多需要用到useContext的值的時候,可以用好幾層不同主題的Provider來包住主程式,實現關注點分離(Separation of concerns),方便維護程式碼。

參考資料
[React Hook 筆記] useContext
實現跨元件資料共享, useContext
Hooks API 參考
Context-React


上一篇
[Day14]用React讓網站動起來:todolist實作-已完成、未完成分頁
下一篇
[Day16]用React讓網站動起來:Context 範例
系列文
用React讓網頁動起來: React基礎與實作30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言