ReactJS setState很慢

zil*_*lla 26 reactjs

我正在尝试使用ReactJS,但是遇到了将其合并到我的表单中的困难.我正在ReactJS中构建一个自动建议表单.在我onChangeQuery,我正在设置状态,然后调用AJAX函数从我的服务器端代码中获取建议; 但是,我注意到这个 loadGroupsFromServer功能没有得到最新状态......这是一个关键的行程太慢了.我知道setState不是即时的,但那我为什么要用setState我的表格呢?使用refs更好吗?最好从中获取价值e.target.value?

救命!

  var GroupForm = React.createClass({
    getInitialState: function() {
      return {query: "", groups: []}
    },
    componentDidMount: function () {
      this.loadGroupsFromServer();
    },
    loadGroupsFromServer: function () {
      $.ajax({
        type: "GET",
        url: this.props.url,
        data: {q: this.state.query},
        dataType: 'json',
        success: function (groups) {
          this.setState({groups: groups});
        }.bind(this),
        error: function (xhr, status, err) {
          console.error(this.props.url, status, err.toString());
        }.bind(this)
      });
    },
    onChangeQuery: function(e) {
      this.setState({query: e.target.value})
      this.loadGroupsFromServer();
    },
    render: function() {
      return (
        <div>
          <form class="form form-horizontal">
            <div class="col-lg-12">
              <input type="text" className="form-control" value={this.state.query} placeholder="Search for groups" onChange={this.onChangeQuery} />
            </div>
          </form>
          <GroupList groups={this.state.groups} />
        </div>
      )
    }
  })
Run Code Online (Sandbox Code Playgroud)

Pau*_*ssy 44

setState采取回调,允许您确保this.loadGroupsFromQuery()仅在this.state更新后调用.

this.setState({...}, function() {
  this.loadGroupsFromQuery();
});
Run Code Online (Sandbox Code Playgroud)


Bur*_*zen 11

setState最佳实践

ES5

this.setState(function(state, props){
   return {
      query: e.target.value
   }
}, function()=>{
   //after callback 
});
Run Code Online (Sandbox Code Playgroud)

ES6

 this.setState((state, props) => ({
    query: e.target.value
 }), ()=>{
   //after callback 
 });
Run Code Online (Sandbox Code Playgroud)


Bri*_*and 6

loadGroupsFromServer应该采用查询参数.

componentDidMount: function () {
  this.loadGroupsFromServer(this.state.query);
},
loadGroupsFromServer: function (query) {
  $.ajax({
    /* ... */
    data: {q: query},
    /* ... */
  });
},
onChangeQuery: function(e) {
  this.setState({query: e.target.value})
  this.loadGroupsFromServer(e.target.value);
},
Run Code Online (Sandbox Code Playgroud)

您通常应该尝试减少对状态的访问,因为它为您提供了更大的灵活性.

根据具体情况,您可能希望在执行某些操作之前等待组件更新:

onChangeQuery: function(e) {
  this.setState({query: e.target.value}, function(){
      this.loadGroupsFromServer(this.state.query)
  }.bind(this));
},
Run Code Online (Sandbox Code Playgroud)

或者你可以像这样重写它,在我看来这更干净.

onChangeQuery: function(e) {
  this.setState({query: e.target.value});
},
componentWillUpdate: function(nextProps, nextState){
  // optionally perform better heuristics, but this prevents them pressing space
  // from triggering an update
  if (nextState.query.trim() !== this.state.query.trim()) {
      this.loadGroupsFromServer(nextState.query);
  }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

您的单字符关闭问题的根本原因是您在设置之前正在读取状态。setState 很快,但它不是即时和同步的。前面的答案为您提供了几种重构方法。


小智 5

setState并不慢,但是它是异步的。因此,根据上面的答案,无论您设置的状态如何,它都会同步工作。

根据最佳实践,状态应该设置在渲染方法之外。