当前位置: 首页 > 面试题库 >

在render中调用setState是不可避免的

山乐生
2023-03-14
问题内容

React文档指出render函数应该是
函数,这意味着它不应该在函数中使用this.setState。但是,我相信当状态依赖于“远程”(即由ajax调用产生的结果)时。唯一的解决方案是setState()render函数内部

就我而言。我们的用户应该可以登录。登录后,我们还需要检查用户的访问权限(ajax调用),以决定如何显示页面。代码是这样的

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是因为当用户单击LOGIN按钮时,页面会重新呈现,并且还需要ajax调用。因此,我想唯一的位置setState就是render违反React原理的函数

有更好的解决方案吗?提前致谢


问题答案:

render始终
保持纯净。在那儿做副作用的东西是非常不好的做法,打电话setState是一个很大的危险信号。在这样的简单示例中,它可以解决问题,但是这是高度不可维护的组件之路,而且它只能起作用,因为副作用是异步的。

相反,请考虑您的组件可能处于的各种状态-就像您在建模状态机一样(事实证明,您是):

  • 初始状态(用户尚未单击按钮)
  • 等待授权(用户单击登录名,但我们尚不知道Ajax请求的结果)
  • 用户有权访问某些内容(我们已经获得了Ajax请求的结果)

使用组件的状态对此建模,您很高兴。

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


 类似资料:
  • React是否在每次调用时重新呈现所有组件和子组件? 如果是,为什么?我认为这个想法是,当状态改变时,只会根据需要提供少量的反应。 我希望只有在数据发生更改时才会出现呈现。 下面是示例的代码,作为JS Fiddle和嵌入的代码片段:

  • 本文向大家介绍在React中如何避免不必要的render?相关面试题,主要包含被问及在React中如何避免不必要的render?时的应答技巧和注意事项,需要的朋友参考一下 shouldComponentUpdate、memoization、PureComponent

  • componentWillMount() 在组件将要挂载时被立即调用. 这个调用发生在render()函数执行之前, 所以如果在componentWillMount里面设置了state, 这个设置的state是不会触发重新渲染的. 同样我们也需要注意不要在componentWillMount()中引入其他可能会导致问题的代码. 如果你有类似的需求, 请在componentDidMount里面完成.

  • 问题内容: 建议在HTML页面中使用表格(现在已经有了CSS)? 表格有什么用途?表具有哪些CSS所没有的功能? 问题答案: 一点都不。但是将表格用于表格数据。只是不要将它们用于一般布局。 但是,如果您显示表格数据(例如结果或什至是表格),请继续使用表格!

  • 问题内容: 我的代码有效,但是我有一个最佳实践问题:状态中有一组对象,并且用户交互一次将更改一个对象的值。 据我所知,我不应该直接更改状态,而是应该始终使用。如果我想不惜一切代价避免这种情况,我将通过迭代深度克隆数组,然后更改克隆。然后将状态设置为克隆。我认为避免改变以后会改变的状态只是降低了我的表现。 详细版本: this.state.data是对象数组。它代表论坛中的主题列表,并且收藏夹按钮将

  • 问题内容: 我有下面列出的3个表: 该SQL描述了我想要的: 问题是,在这种情况下,我有一个很大的NOT IN值,据我所知它将影响服务器性能(我不确定,因为我从未尝试对其进行基准测试或Google评估)。有什么建议吗? 问题答案: 试试这个 :