其实我之前也遇到过类似的情况。我假设您遇到的错误是这样的:
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 个工具来帮助您实现这一目标。
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() {
...
}
});
renderToStringAsync()
- 它允许你渲染服务器端
ReactAsync.renderToStringAsync(
<AwesomeComponent />,
function(err, markup, data) {
res.send(markup);
})
);
injectIntoMarkup()
- 这将注入服务器状态以及标记以确保它在客户端可用
ReactAsync.renderToStringAsync(
<AwesomeComponent />,
function(err, markup, data) {
res.send(ReactAsync.injectIntoMarkup(markup, data, ['./app.js']));
})
);
react-async
提供比这更多的功能。您应该查看react-async 文档以获取其功能的完整列表,以及对我上面简要描述的功能的更全面的解释。