小编典典

从componentWillMount中的异步调用返回尝试设置setState时未定义文档

reactjs

我在我的组件的componentWillMount调用中获取了数据(实际上是在mixin中,但想法相同)。在ajax调用返回后,我尝试设置为setState,但是出现错误消息,即未定义文档。

我不确定该如何解决。还有什么要等待的吗?一个承诺或回调我应该在其中做setState吗?

这就是我想要做的:

componentWillMount: function() {
    request.get(this.fullUrl()).end(function(err, res) {
        this.setState({data: res.body});
    }.bind(this));
}

阅读 798

收藏
2020-07-22

共1个答案

小编典典

我实际上曾经遇到过类似的情况。我认为您遇到的错误是这样的:

Uncaught Error: Invariant Violation: replaceState(...): Can only update a mounted or mounting component.

该错误是由于以下事实造成的:在React组件中,无法在安装组件之前设置状态。因此,componentWillMount与其尝试在中设置状态,不如在中进行设置componentDidMount。我通常会加一张.isMounted()支票,只是为了很好。

尝试这样的事情:

    componentDidMount: function () {
      request.get(this.fullUrl()).end(function(err, res) {
        if (this.isMounted()) {
          this.setState({data: res.body});
        }
      }.bind(this));
    }

编辑: 忘记提及…如果组件在异步操作完成之前被“卸载”,则您也可能会遇到错误。

如果异步操作是“可取消的”,则可以轻松处理。假设您的request()上述superagent要求类似(可以取消),那么我将执行以下操作以避免任何潜在的错误。

    componentDidMount: function () {
      this.req = request.get(this.fullUrl()).end(function(err, res) {
        if (this.isMounted()) {
          this.setState({data: res.body});
        }
      }.bind(this));
    },

    componentWillUnmount: function () {
      this.req.abort();
    }

编辑#2: 在我们的评论之一中,您提到您的意图是创建一个可以异步加载状态的同构解决方案。虽然这超出了原始问题的范围,但我建议您检查一下react-
async
。开箱即用,它提供3个工具可以帮助您实现此目标。

  1. getInitialStateAsync -这是通过mixin提供的,它允许组件异步获取状态数据。
        var React = require('react')
    var ReactAsync = require('react-async')

    var AwesomeComponent = React.createClass({
      mixins: [ReactAsync.Mixin],

      getInitialStateAsync: function(callback) {
        doAsyncStuff('/path/to/async/data', function(data) {
          callback(null, data)
        }.bind(this))
      },

      render: function() {
         ... 
      }
    });
  1. renderToStringAsync() -允许您渲染服务器端
        ReactAsync.renderToStringAsync(
      <AwesomeComponent />,
      function(err, markup, data) {
        res.send(markup);
      })
    );
  1. injectIntoMarkup() -它将注入服务器状态以及标记以确保其在客户端可用
        ReactAsync.renderToStringAsync(
      <AwesomeComponent />,
      function(err, markup, data) {
        res.send(ReactAsync.injectIntoMarkup(markup, data, ['./app.js']));
      })
    );

react-async提供的功能远不止于此。您应该查看react-async文档以获取其功能的完整列表,以及对我上面简要介绍的功能的更全面的解释。

2020-07-22