Eson Wong's Blog

编程笔记,投资记录, 读书总结, 生活心得

0%

怎么使用 React Context API ?

React context 是 React 提供的基本工具,用于在组件间共享状态。

本文介绍 React context 的基本用法。

React Context API

什么是 React Context?

React context 允许我们不对组件树的每层组件手动添加 props 来传递数据的情况下,在组件间共享数据。它能让我们更容易的跨组件共享状态。

什么时候使用 React Context?

当某些状态可能在任何组件中都会被使用时,React context 是非常有用的。

比如:

  • UI 主题状态(亮暗模式、用户定制的 UI 风格等)
  • 当前会话的用户数据(用户名、头像等)
  • 当前语言或区域

React context 会让项目里的任何组件都能轻松访问到这些状态。

React context 解决了什么问题?

React context 帮我们解决了 props drilling 问题。

Props drilling 是指状态以 props 的形式从 React 组件树中一直往下传递, 但中间层组件并不需要这些 props, 只是做一个向下转发,这种情况就叫做 props drilling。

下面是一个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
export default function App() {
const [user, setUser] = useState({ name: 'Eson', age: 18 });

return (
<Header user={user}>
)
}

const Header = ({ user }) => {
return (
<>
<Menu user={user}>
</>
)
}

你可以看到,Header 组件中的 user 状态是通过 props drilling 来获取的。App 的直接子组件 Header 并不需要 user 状态,它只是做一个向下转发。

怎么使用 React context?

  1. 使用 React context API React.createContext 方法创建 context

    1
    2
    3
    const UserContext = React.createContext({ name: "Eson", age: 18 }); // 第一个参数是默认值

    export default UserContext;
  2. 使用 React context 的 Provider 组件包裹你的组件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import React, { useState } from "react";
    import UserContext from "userContext.js";

    const App = () => {
    const [user, setUser] = useState({ name: "Eson", age: 18 });

    return (
    <UserContext.Provider value={user}>
    <Header />
    </UserContext.Provider>
    );
    };
  3. 使用 React context 的 Consumer 组件获取 context 状态,提供给使用状态的组件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import React from "react";
    import UserContext from "userContext.js";

    const Header = () => {
    return <Menu />;
    };

    const Menu = () => {
    return (
    <UserContext.Consumer>
    {(user) => (
    <div>
    {user.name}
    <button>退出</button>
    </div>
    )}
    </UserContext.Consumer>
    );
    };

上面的示例代码中,被 UserContext.Provider 组件包裹的组件树才可以通过 UserContext.Consumer 组件来获取用户的状态。

Context hook

随着 React 带来了 Hooks,我们可以使用 useContext 来获取 context 状态。

`useContext`` 接收一个 context 对象,返回一个 context 的值。它使我们的组件更加简洁,并允许我们创建自己的自定义钩子。

1
2
3
4
5
6
7
8
9
10
11
12
13
import React, { useContext } from "react";
import UserContext from "userContext.js";

const Menu = () => {
const user = useContext(UserContext);

return (
<div>
{user.name}
<button>退出</button>
</div>
);
};

使用 React context 的注意事项

解决 props drilling 的问题,React context 可以解决,但是它不是一个好的选择。第一是因为这会让组件的复用性变差,第二是 context 状态如果是一个对象,更新的时候会导致所有使用这个 context 的组件重新渲染,即使仅使用了未更新的属性值。

我们也可以更好组合我们的组件来解决这个问题,比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import React from "react";

const App = () => {
const [user, setUser] = useState({ name: "Eson", age: 18 });

return (
<Header>
<Menu user={user} />
</Header>
);
};

const Header = ({ children }) => {
return <header>{children}</header>;
};

const Menu = ({ user }) => {
return (
<div>
{user.name}
<button>退出</button>
</div>
);
};

欢迎关注我的其它发布渠道