调用的setState在渲染是不可以避免的 [英] Calling setState in render is not avoidable

查看:961
本文介绍了调用的setState在渲染是不可以避免的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

阵营文件指出,在渲染函数应 纯粹这意味着它不应该使用 this.setState 在里面。但是,我相信,当国家决定于远程,即从阿贾克斯独特叫声唯一的解决办法的结果是的setState()渲染函数

React document states that the render function should be pure which mean it should not use this.setState in it .However, I believe when the state is depended on 'remote' i.e. result from ajax call.The only solution is setState() inside a render function

在我case.Our用户应该能够登录。登录后,我们还需要检查用户的访问(Ajax调用)来决定如何显示PAGE电泳code是像这样

In my case.Our users can should be able to log in. After login, We also need check the user's access (ajax call )to decide how to display the page.The code is something like this

React.createClass({
     render:function(){
          if(this.state.user.login)
          {
              //do not call it twice
              if(this.state.callAjax)
              {
              var self=this
              $.ajax{
                  success:function(result)
                  {
                      if(result==a) 
                      {self.setState({callAjax:false,hasAccess:a})}
                      if(result==b) 
                      {self.setState({callAjax:false,hasAccess:b})}

                  }
              }
              }
              if(this.state.hasAccess==a) return <Page />
              else if(this.state.hasAccess==a) return <AnotherPage />
              else return <LoadingPage />
          }
          else
          {
            return <div>
                   <button onClick:{
                   function(){this.setState({user.login:true})}
                   }> 
                   LOGIN
                   </button>
                   </div>
          }
     }
})

Ajax调用。所以我想唯一的地方为<不能出现在 componentDidMount ,因为当用户点击登录按钮,该网页重新渲染,并且还需要Ajax调用code>的setState 里面的渲染功能,违反原则做出反应。

The ajax call can not appear in componentDidMount because when user click LOGIN button the page is re-rendered and also need ajax call .So I suppose the only place to setState is inside the render function which breach the React principle

没有更好的办法?在此先感谢

Any better solutions ? Thanks in advance

推荐答案

渲染应的总是的保持纯洁。这是一个非常不好的做法,做到边effecty的东西在里面,并调用的setState 是一个大红旗;在这样一个简单的例子就可以工作了好了,但它的道路,高度不可维护的部件,再加上它只能是因为副作用是异步。

render should always remain pure. It's a very bad practice to do side-effecty things in there, and calling setState is a big red flag; in a simple example like this it can work out okay, but it's the road to highly unmaintainable components, plus it only works because the side effect is async.

相反,想想各种状态的组件可以在 - 就像你在模拟一个状态机(事实证明这,你是):

Instead, think about the various states your component can be in — like you were modeling a state machine (which, it turns out, you are):


  • 初始状态(用户没有点击按钮)

  • 待授权(用户点击登录,但我们不知道的Ajax请求的结果还)

  • 用户有权访问的东西(我们已经拿到了Ajax请求的结果)

与组件的状态模型了这一点,你是好去。

Model this out with your component's state and you're good to go.

React.createClass({
  getInitialState: function() {
    return {
      busy: false, // waiting for the ajax request
      hasAccess: null, // what the user has access to
      /**
       * Our three states are modeled with this data:
       *
       * Pending: busy === true
       * Has Access: hasAccess !==  null
       * Initial/Default: busy === false, hasAccess === null
       */
    };
  },

  handleButtonClick: function() {
    if (this.state.busy) return;

    this.setState({ busy: true }); // we're waiting for ajax now
    this._checkAuthorization();
  },

  _checkAuthorization: function() {
    $.ajax({
      // ...,
      success: this._handleAjaxResult
    });
  },

  _handleAjaxResult: function(result) {
    if(result === a) {
      this.setState({ hasAccess: a })
    } else if(result ===b ) {
      this.setState({ hasAccess: b })
    }
  },

  render: function() {
    // handle each of our possible states
    if (this.state.busy) { // the pending state
      return <LoadingPage />;
    } else if (this.state.hasAccess) { // has access to something
      return this._getPage(this.state.hasAccess);
    } else {
      return <button onClick={this.handleButtonClick}>LOGIN</button>;
    }
  },

  _getPage: function(access) {
    switch (access) {
    case a:
      return <Page />;
    case b:
      return <AnotherPage />;
    default:
      return <SomeDefaultPage />;
    }
  }
});

这篇关于调用的setState在渲染是不可以避免的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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