【问题标题】:Issuing AJAX request in the callback of setState()在 setState() 的回调中发出 AJAX 请求
【发布时间】:2015-04-30 16:36:45
【问题描述】:

我一直在编写这样的 ReactJS AJAX 请求:

this.setState({
    isLoading: true,
    results: null
});
$.get(ajaxUrl, function(results) {
    this.setState({
        isLoading: false,
        results: results
    });
}.bind(this));

这只是一个例子,它缺乏错误处理、限制、取消请求等。但要点就在那里。我基本上要求设置一些状态,然后然后发出请求。

查看 GitHub 上的一些其他代码,但我注意到有些人在 setState 回调中编写 AJAX 调用:

this.setState({
    isLoading: true,
    results: null
}, function() {
    $.get(ajaxUrl, function(results) {
        this.setState({
            isLoading: false,
            results: results
        });
    }.bind(this));
}.bind(this));

这样做有正当理由吗? The docs say:

不保证 setState 调用的同步操作,调用可能会被批处理以提高性能。

因此不能保证 setState 在返回之前会改变状态,但我没有看到不同的 setState 可能会乱序执行。所以可能发生的最坏情况是“加载”状态永远不会被渲染。这是后一种风格试图解决的问题吗?还有其他一些我没有看到的风险吗?

【问题讨论】:

    标签: ajax concurrency reactjs


    【解决方案1】:

    但我没有提到不同的 setState 可能会乱序执行

    正确,它们是按顺序运行的,从用户体验的角度来看,您不希望显示加载指示器的时间少于半秒。

    需要这个的情况看起来更像这样:

    this.setState({
        isLoading: true,
        results: this.state.results || []
    }, function() {
        $.get(ajaxUrl, function(results) {
            this.setState({
                isLoading: false,
                // note! we're referring to state here
                results: this.state.results.concat(results)
            });
        }.bind(this));
    }.bind(this));
    

    但是,这也可以通过将回调传递给 setState 而不是对象来解决。这样,我们可以在任何先前的队列更新发生后查看状态。

    也可以传递带有签名函数(状态,道具)的函数。在某些情况下,当您希望在设置任何值之前将原子更新排入队列,该更新在设置任何值之前参考 state+props 的先前值。
    – Component Api Docs

    this.setState({
        isLoading: true,
        results: null
    });
    $.get(ajaxUrl, function(results) {
        this.setState(function(state){
            return {
                isLoading: false,
                results: state.results.concat(results)
            };
        });
    }.bind(this));
    

    为了获得最佳效果,请将所有这些抽象为一个高阶组件或 mixin。您不想在每个获取数据的组件中处理此逻辑。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-22
      • 2019-02-25
      • 2015-07-08
      • 1970-01-01
      • 1970-01-01
      • 2018-08-23
      相关资源
      最近更新 更多