我实际上曾经遇到过类似的情况。我认为您遇到的错误是这样的:
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();
}
在我们的评论之一中,您提到您的意图是创建一个可以异步加载状态的同构解决方案。虽然这超出了原始问题的范围,但我建议您检查一下react- async。开箱即用,它提供3个工具可以帮助您实现此目标。
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() {
...
}
});
ReactAsync.renderToStringAsync(
<AwesomeComponent />,
function(err, markup, data) {
res.send(markup);
})
);
ReactAsync.renderToStringAsync(
<AwesomeComponent />,
function(err, markup, data) {
res.send(ReactAsync.injectIntoMarkup(markup, data, ['./app.js']));
})
);
react-async
提供的功能远不止于此。您应该查看react-async文档以获取其功能的完整列表,以及对我上面简要介绍的功能的更全面的解释。