React 利用Context实现组件通信

「这是我参与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中。这样,被包裹的所有组件,都能直接拿到这两个参数了。

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中,向下传递
        <MyContext.Provider value={{ count, setCount }}>
            A组件
            <B />
            <C />
        </MyContext.Provider>
    );
};

export default A;
复制代码

E组件需要从A中引入创建的context对象MyContext,并使用useContext方法,从MyContext中拿到其中的参数。

// 引入创建的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方法。

// 引入创建的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中,并导出:

// contextManager.js

import { createContext } from 'react';

export const MyContext = createContext();

// 定义的其他context
export const MyContext2 = createContext();
export const MyContext3 = createContext();
复制代码

猜你喜欢

转载自juejin.im/post/7034484377715212295