在渲染函数之外访问 React Context

新手上路,请多包涵

我正在使用新的 React Context API 而不是 Redux 开发一个新应用程序,之前使用 Redux ,例如,当我需要获取用户列表时,我只需调用 componentDidMount 我的动作,但是现在有了 React Context,我的动作在我的 Consumer 中,它在我的渲染函数中,这意味着每次调用我的渲染函数时,它都会调用我的动作来获取我的用户列表,这不好,因为我会做很多不必要的请求。

那么,我如何才能只调用一次我的操作,例如在 componentDidMount 而不是调用渲染?

举个例子,看看这段代码:

假设我将所有 Providers 包装在一个组件中,如下所示:

 import React from 'react';

import UserProvider from './UserProvider';
import PostProvider from './PostProvider';

export default class Provider extends React.Component {
  render(){
    return(
      <UserProvider>
        <PostProvider>
          {this.props.children}
        </PostProvider>
      </UserProvider>
    )
  }
}

然后我把这个 Provider 组件包装了我的所有应用程序,如下所示:

 import React from 'react';
import Provider from './providers/Provider';
import { Router } from './Router';

export default class App extends React.Component {
  render() {
    const Component = Router();
    return(
      <Provider>
        <Component />
      </Provider>
    )
  }
}

现在,例如,在我的用户视图中,它将是这样的:

 import React from 'react';
import UserContext from '../contexts/UserContext';

export default class Users extends React.Component {
  render(){
    return(
      <UserContext.Consumer>
        {({getUsers, users}) => {
          getUsers();
          return(
            <h1>Users</h1>
            <ul>
              {users.map(user) => (
                <li>{user.name}</li>
              )}
            </ul>
          )
        }}
      </UserContext.Consumer>
    )
  }
}

我想要的是这样的:

 import React from 'react';
import UserContext from '../contexts/UserContext';

export default class Users extends React.Component {
  componentDidMount(){
    this.props.getUsers();
  }

  render(){
    return(
      <UserContext.Consumer>
        {({users}) => {
          getUsers();
          return(
            <h1>Users</h1>
            <ul>
              {users.map(user) => (
                <li>{user.name}</li>
              )}
            </ul>
          )
        }}
      </UserContext.Consumer>
    )
  }
}

但是当然上面的例子不起作用,因为 getUsers 不在我的用户视图道具中。如果可能的话,正确的方法是什么?

原文由 Gustavo Mendonça 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 687
2 个回答

编辑: 随着 v16.8.0 中 react-hooks 的引入,您可以通过使用 useContext hook 在功能组件中使用上下文

const Users = () => {
    const contextValue = useContext(UserContext);
    // rest logic here
}

编辑: 从版本 16.6.0 开始。您可以使用 this.context 在生命周期方法中使用上下文

class Users extends React.Component {
  componentDidMount() {
    let value = this.context;
    /* perform a side-effect at mount using the value of UserContext */
  }
  componentDidUpdate() {
    let value = this.context;
    /* ... */
  }
  componentWillUnmount() {
    let value = this.context;
    /* ... */
  }
  render() {
    let value = this.context;
    /* render something based on the value of UserContext */
  }
}
Users.contextType = UserContext; // This part is important to access context values


在 16.6.0 版本之前,您可以通过以下方式进行操作

为了在你的生命周期方法中使用上下文,你可以编写你的组件,比如

class Users extends React.Component {
  componentDidMount(){
    this.props.getUsers();
  }

  render(){
    const { users } = this.props;
    return(

            <h1>Users</h1>
            <ul>
              {users.map(user) => (
                <li>{user.name}</li>
              )}
            </ul>
    )
  }
}
export default props => ( <UserContext.Consumer>
        {({users, getUsers}) => {
           return <Users {...props} users={users} getUsers={getUsers} />
        }}
      </UserContext.Consumer>
)

通常,您会在您的应用程序中维护一个上下文,并且将上述登录信息打包到 HOC 中以便重用它是有意义的。你可以这样写

import UserContext from 'path/to/UserContext';

const withUserContext = Component => {
  return props => {
    return (
      <UserContext.Consumer>
        {({users, getUsers}) => {
          return <Component {...props} users={users} getUsers={getUsers} />;
        }}
      </UserContext.Consumer>
    );
  };
};

然后你可以像这样使用它

export default withUserContext(User);

原文由 Shubham Khatri 发布,翻译遵循 CC BY-SA 4.0 许可协议

好的,我找到了一种有限制的方法。使用 with-context 库,我设法将我所有的消费者数据插入到我的组件道具中。

但是,将多个消费者插入同一个组件是一件很复杂的事情,你必须使用这个库创建混合消费者,这使得代码不优雅且效率低下。

这个库的链接: https ://github.com/SunHuawei/with-context

编辑:实际上你不需要使用 with-context 提供的多上下文 api,事实上,你可以使用简单的 api 并为你的每个上下文制作一个装饰器,如果你想使用超过您组件中的一个消费者,只需在您的班级上方声明您想要的装饰器即可!

原文由 Gustavo Mendonça 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进