React 利用Context實現元件通訊

語言: CN / TW / HK

「這是我參與11月更文挑戰的第24天,活動詳情檢視:2021最後一次更文挑戰」。

本文是自己學習useContext的筆記。

1. 兩元件通訊

React 中,父子元件需要通訊時,父元件可以將引數寫在props中傳遞給子元件,實現父元件向子元件通訊;父元件還可以傳遞一個函式給子元件,子元件呼叫這個函式,實現子元件向父元件的通訊。這就完成了父子元件的相互通訊。

但當元件巢狀關係複雜的時候,如下圖所示,A元件下有B元件和C元件,B元件下有D元件,C元件下有E元件。

當需要在A元件和D元件之間通訊時,也可以採取上述的方法,A通過props一層一層傳遞引數到D元件,D元件再呼叫函式,一層一層返回到A元件。

2. Context

但當元件巢狀關係更復雜時,這樣的方式極其繁瑣,且不易維護。這裡介紹一種使用Context實現元件通訊的方式。

Context 提供了一個無需為每層元件手動新增 props,就能在元件樹間進行資料傳遞的方法。

使用Context,可以避免通過中間元件傳遞props。有的時候在元件樹中很多不同層級的元件需要訪問同一批資料Context能讓你將這些資料向元件樹下所有的元件進行廣播,所有的元件都能訪問到這些資料,也能訪問到後續的資料更新。

3. useContext 實踐

首先實現上述關係的元件:

要實現的效果為,E元件中點選add,會增加計數值。點選D元件的clear按鈕,會對E元件的計數值進行清零

A元件中,需要從react中匯入createContext方法,在元件外部建立Context物件,並匯出。同時,需要用<MyContext.Provider></MyContext.Provider>進行包裹,其中,MyContext是自定義的名稱。資料物件放在<MyContext.Provider>value中。這樣,被包裹的所有元件,都能直接拿到這兩個引數了。

```javascript import { createContext, useState } from 'react'; import B from './B'; import C from './C'; import './index.css';

// 在元件外部建立Context物件,並匯出 export const MyContext = createContext();

const A = () => { const [count, setCount] = useState(0); return ( // 資料物件放在value中,向下傳遞 A元件 ); };

export default A; ```

E元件需要從A中引入建立的context物件MyContext,並使用useContext方法,從MyContext中拿到其中的引數。

```javascript // 引入建立的context import { MyContext } from './A'; import { useContext } from 'react';

const E = () => { // 拿到兩個引數 const { count, setCount } = useContext(MyContext);

return (
    <div>
        我是E, 計數值:{count}
        <button onClick={() => setCount(count => count + 1)}>add</button>
    </div>
);

};

export default E; ```

D元件也需要從A中引入建立的context物件MyContext,使用useContext方法,拿到setCount方法。

```javascript // 引入建立的context import { MyContext } from './A'; import { useContext } from 'react';

const D = () => { // 拿到引數 const { setCount } = useContext(MyContext);

return (
    <div>
        我是D
        <button onClick={() => setCount(0)}>clear</button>
    </div>
);

};

export default D; ```

這樣,E元件和D元件使用的是同一批資料,也能訪問到這些資料的更新,實現了跨元件通訊。

4. 集中式管理 Context 物件

如果一個專案中,多處使用context,會造成程式碼結構不清晰,不便於維護。這時可以將所有建立context的程式碼,放入到專門的檔案中,進行集中管理,需要用到的地方,都從此檔案引入即可。

例如,將建立的所有Context物件放入contextManager.js中,並匯出:

```javascript // contextManager.js

import { createContext } from 'react';

export const MyContext = createContext();

// 定義的其他context export const MyContext2 = createContext(); export const MyContext3 = createContext(); ```