如何使用 React Context 管理用户状态

介绍

在 React 中,数据通常从顶部到底部通过插件(父母组件到儿童组件)流动,但这并不总是理想的。

在这种情况下,使用 Redux来管理状态似乎是一个好主意,但许多人认为 这不应该是你的第一个选择

React Context是一个替代的解决方案,可以通过组件共享数据,而无需在每个级别上手动传递准则。

在本文中,您将探索背景API,并了解如何使用它来管理用户状态。

前提条件

要跟随这篇文章,你将需要:

  • 熟悉 React 基础知识,如嵌入式 Components, propsstate将是有益的。

本教程已通过 Node v15.3.0、npm v6.14.9 和 react v17.0.1 进行验证。

了解问题

以下是通过用户avatarSize的组件的示例:

1<Page user={user} avatarSize={avatarSize} />

使一个PageLayout组件:

1<PageLayout user={user} avatarSize={avatarSize} />

使一个NavigationBar组件:

1<NavigationBar user={user} avatarSize={avatarSize} />

返回一个链接Avatar,使用用户avatarSize特征:

1<Link href={user.permalink}>
2  <Avatar user={user} size={avatarSize} />
3</Link>

在上面的例子中,只有Avatar组件实际上使用了用户组件,但是它的每个祖先组件(父母,祖父母等)都接收了用户并将其传递下来,这意味着如果Avatar组件在未来需要另一个组件,你将不得不确保它的每个祖先组件接收和传递它。

实际上,用户状态需要在许多不同的组件中共享,因此通过它作为一个支撑将导致它比上面的例子更深入。

创建React.createContext

React.createContext 方法返回一个Context 对象. 这个Context 对象配备了两个重要的 React 组件,允许用户订阅数据:供应商消费者

当 React 返回订阅此背景对象的组件时,它会读取树上最接近匹配的提供商组件的当前背景值。

「CreateContext」方法采用可选的「默认值」参数,如果在树中找不到匹配的「Context.Provider」组件,则将其提供给「Context.Consumer」。

创建一个背景对象,并将其导出用于其他组件:

1[label src/userContext.js]
2import React from 'react';
3
4const userContext = React.createContext({user: {}});
5
6export { userContext };

在上面的示例中,您初始化了userContext,并提供了DefaultValue{user: {}}

现在你有一个背景对象,你可以为它提供一个值,并订阅更改。

应用Context.Provider

将用户状态作为值传输到context.Provider,这样它就可以被context.Consumer消耗:

 1[label src/App.js]
 2import React from 'react';
 3
 4import Main from './Main';
 5
 6import {userContext} from './userContext';
 7
 8class App extends React.Component {
 9  constructor(props) {
10    super(props);
11    this.state = {
12      user: {}
13    };
14  }
15
16  componentDidMount() {
17    // get and set currently logged in user to state
18  }
19
20  render() {
21    return (
22      <userContext.Provider value={this.state.user}>
23        <Main/>
24      </userContext.Provider>
25    );
26  }
27}
28
29export default App;

这是一个很好的开始,包装组件与userContext.Provider确保您传递的价值可以消耗在任何的后代子组件中。

应用Context.Consumer

userContext.Consumer 接收一个函数作为一个孩子. 该函数接收当前的背景值(作为向 userContext.Provider 传递的代码的值)并返回一个 React 节点。

 1[label src/Main.js]
 2import Sidebar from './Sidebar';
 3import Content from './Content';
 4import Avatar from './Avatar';
 5
 6import {userContext} from './userContext';
 7
 8function Main(props) {
 9  return (
10    <Sidebar/>
11    <userContext.Consumer>
12      {({value}) => {
13        <Avatar value={value}/>
14      }}
15    </userContext.Consumer>
16    <Content/>
17  )
18}
19
20export default Main;

在这种情况下,它将应用程序组件的state.user作为值,并返回一个Avatar组件。

从嵌入式组件中更新背景

到目前为止,您已经使用 React Context 将数据传输到需要数据的组件中,而无需手动传输附件。

考虑一个按钮来登录用户。

在这种情况下,您可以通过相同的背景传递函数,以允许消费者更新该背景。

 1[label src/App.js]
 2import React from 'react';
 3
 4import Main from './Main';
 5
 6import {userContext} from './userContext';
 7
 8class App extends React.Component {
 9  constructor(props) {
10    super(props);
11    this.state = {
12      user: {}
13    };
14
15    this.logout = this.logout.bind(this);
16  }
17
18  logout() {
19    this.setState({user: {}});
20  }
21
22  componentDidMount() {
23    // get and set currently logged in user to state
24  }
25
26  render() {
27    const value = {
28      user: this.state.user,
29      logoutUser: this.logout
30    }
31
32    return (
33      <userContext.Provider value={value}>
34        <Main/>
35      </userContext.Provider>
36    );
37  }
38}
39
40export default App;

传递到更新背景的函数可以在userContext.Provider组件中的任何嵌入组件中使用。

 1[label src/Main.js]
 2import Sidebar from './Sidebar';
 3import Content from './Content';
 4import Avatar from './Avatar';
 5import LogoutButton from './LogoutButton';
 6
 7import {userContext} from './userContext';
 8
 9function Main(props) {
10  return (
11    <Sidebar/>
12    <userContext.Consumer>
13      {({user, logoutUser}) => {
14        return (
15          <Avatar user={user}/>
16          <LogoutButton onClick={logoutUser}/>
17        );
18      }}
19    </userContext.Consumer>
20    <Content/>
21  )
22}
23
24export default Main;

登录按钮已被添加到主要组件中。

这就总结了如何使用React的Context API来管理用户状态的例子。

结论

在本文中,您被介绍了 React Context,并使用Context.ProducerContext.Consumer

如果您想了解更多关于 React 的信息,请查看我们的 如何在 React.js 中编码系列,或查看 我们的 React 主题页面以获取练习和编程项目。

Published At
Categories with 技术
Tagged with
comments powered by Disqus