在渲染函数之外访问 React Context [英] Access React Context outside of render function

查看:51
本文介绍了在渲染函数之外访问 React Context的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am developing a new app using the new React Context API instead of Redux, and before, with Redux, when I needed to get a list of users for example, I simply call in componentDidMount my action, but now with React Context, my actions live inside my Consumer which is inside my render function, which means that every time my render function is called, it will call my action to get my users list and that is not good because I will be doing a lot of unecessary requests.

那么,如何只调用一次我的操作,例如在 componentDidMount 中而不是在 render 中调用?

So, how I can call only one time my action, like in componentDidMount instead of calling in render?

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

Just to exemplify, look at this code:

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

Let's suppose that I am wrapping all my Providers in one component, like this:

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 组件包装在我所有的应用程序中,就像这样:

Then I put this Provider component wrapping all my app, like this:

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>
    )
  }
}

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

Now, at my users view for example, it will be something like this:

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 不在我的用户视图道具中.如果可能的话,正确的做法是什么?

But ofcourse that the example above don't work because the getUsers don't live in my Users view props. What is the right way to do it if this is possible at all?

推荐答案

随着 v16.8.0 中 react-hooks 的引入,您可以在通过使用 useContext 钩子>

With the introduction of react-hooks in v16.8.0, you can use context in functional components by making use of useContext hook

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

编辑:从 16.6.0 版本开始.您可以使用 this.context

From version 16.6.0 onwards. You can make use of context in lifecycle method using this.context like

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 版本之前,您可以通过以下方式进行


Prior to version 16.6.0, you could do it in the following manner

为了在你的生命周期方法中使用 Context,你可以像这样编写组件

In order to use Context in your lifecyle method, you would write your component like

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 中以便重用它是有意义的.你可以这样写

Generally you would maintain one context in your App and it makes sense to package the above login in an HOC so as to reuse it. You can write it like

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);

这篇关于在渲染函数之外访问 React Context的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆