为了账号安全,请及时绑定邮箱和手机立即绑定

在渲染功能之外访问React Context

在渲染功能之外访问React Context

繁华开满天机 2019-10-09 16:02:55
我正在使用新的React Context API而不是Redux开发一个新应用,并且在使用之前,例如Redux,当我需要获取用户列表时,我只是调用componentDidMount我的操作,但是现在使用React Context,我的操作可以在内部进行。我的用户位于我的渲染函数中,这意味着每次调用我的渲染函数时,它将调用我的操作以获取用户列表,但这不好,因为我将执行许多不必要的请求。那么,如何只能一次调用动作,例如in componentDidMount而不是调用render?只是为了举例说明,请看以下代码:假设我将所有内容包装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不存在于我的用户视图中的道具。如果有可能,正确的方法是什么?
查看完整描述

3 回答

?
MMMHUHU

TA贡献1834条经验 获得超8个赞

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


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之前,您可以按以下方式进行操作


为了在您的生命周期方法中使用Context,您可以将组件编写为


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


查看完整回答
反对 回复 2019-10-09
?
ibeautiful

TA贡献1993条经验 获得超5个赞

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


但是,要在同一个组件中插入多个使用方很复杂,您必须使用此库创建混合使用方,这会使代码不够美观且效率低下。


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


编辑:实际上,您不需要使用提供的多上下文api,with-context实际上,您可以使用简单的api并为每个上下文创建一个装饰器,如果您想在组件中使用多个消费者,则只需在类上声明所需的装饰数!


查看完整回答
反对 回复 2019-10-09
  • 3 回答
  • 0 关注
  • 684 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信