Jas*_*ell 11 reactjs node-request
我在我的组件的componentWillMount调用中抓取了我的数据[实际上它是在mixin中,但同样的想法].在ajax调用返回后,我尝试setState,但是我得到了文档未定义的错误.
我不知道怎么解决这个问题.有什么值得期待的吗?承诺或回调我应该在做setState吗?
这就是我想要做的:
componentWillMount: function() {
request.get(this.fullUrl()).end(function(err, res) {
this.setState({data: res.body});
}.bind(this));
}
Run Code Online (Sandbox Code Playgroud)
在内部进行异步操作并不是一个好主意componentWillMount.你真的应该这样做,componentDidMount因为如果组件做的第一个任务是获取一些数据 - 你可能希望它在获取数据之前显示一个微调器或某种加载通知器.
因此,我个人从不做你正在做的事,componentDidMount每次都选择.然后,您可以设置初始状态,以便第一个安装渲染向用户显示加载微调器或其他某种初始状态.ajax会触发,一旦得到响应,您就会更新.通过这种方式,您知道您正在处理用户处于糟糕连接状态的情况,例如接收不良的移动设备等,通过让用户知道某个组件正在加载某些数据来提供良好的用户体验,这就是为什么他们不会什么都看不到.
这就是说,为什么在执行某些异步函数时会出现错误componentWillMount- 因为如果你只是this.setState在生命周期函数内部调用它,它会正常工作吗?这是React工作原理的一个怪癖,据我所知,至少从React 0.11开始.当你挂载一个组件时,this.setState在内部同步执行componentWillMount工作就好了(虽然在0.12.x中有一个错误,其中传递给setState内部的任何函数回调componentWillMount都不会被执行).这是因为React意识到你正在一个尚未安装的组件上设置状态 - 这是你通常无法做到的事情 - 但是它允许它在componentWillMount特殊的生命周期功能中.但是,当您对该setState调用进行异步处理时,它将不再受到特殊处理,并且正常规则适用 - 您无法setState在未安装的组件上进行处理.如果您的ajax请求返回非常快,那么您的setState调用完全可能在componentWillMount相位之后发生,但在组件实际安装之前 - 并且您收到错误.如果事实上你的ajax请求没有显然那么快,比如花了一秒钟或更长时间,那么你可能不会注意到错误,因为你的组件极有可能在一秒内完全安装,所以你的setState呼叫变成了再次通过正常规则有效.但是你在这里基本上给自己一个竞争条件,安全并使用componentDidMount- 因为它也比我上面谈到的其他原因更好.
有些人说你可以在一个内部做到这一点setTimeout并且它们是正确的,但这主要是因为你将你的请求所花费的时间增加到最小x,这通常足以迫使它setState在组件安装后执行-如此有效地你可能一直在做你的setState内部componentDidMount而不是依赖于setTimeout计时器中的组件安装.
TL; DR回答:
虽然不推荐,但您可以同步setState内部componentWillMount.理想情况下,您可以使用同步执行此操作的任何情况getInitialState.
但是,setState异步使用componentWillMount是非常不明智的,因为它会根据您的异步任务所需的时间打开潜在的竞争条件.componentDidMount改为使用并使用该初始渲染来显示加载微调器或类似:)
我以前遇到过类似的情况.我假设您遇到的错误是这样的:
Uncaught Error: Invariant Violation: replaceState(...): Can only update a mounted or mounting component.
Run Code Online (Sandbox Code Playgroud)
该错误是由以下事实引起的:在React组件中,您无法在安装组件之前设置状态.所以,不componentWillMount应该尝试设置状态,而应该进行componentDidMount.我通常添加一张.isMounted()支票,只是为了好的措施.
尝试这样的事情:
componentDidMount: function () {
request.get(this.fullUrl()).end(function(err, res) {
if (this.isMounted()) {
this.setState({data: res.body});
}
}.bind(this));
}
Run Code Online (Sandbox Code Playgroud)
如果异步操作是"可取消",则可以轻松处理.假设您的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();
}
Run Code Online (Sandbox Code Playgroud)
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() {
...
}
});
Run Code Online (Sandbox Code Playgroud)renderToStringAsync() - 允许您渲染服务器端
ReactAsync.renderToStringAsync(
<AwesomeComponent />,
function(err, markup, data) {
res.send(markup);
})
);
Run Code Online (Sandbox Code Playgroud)injectIntoMarkup() - 它将注入服务器状态以及标记,以确保它可用于客户端
ReactAsync.renderToStringAsync(
<AwesomeComponent />,
function(err, markup, data) {
res.send(ReactAsync.injectIntoMarkup(markup, data, ['./app.js']));
})
);
Run Code Online (Sandbox Code Playgroud)react-async提供了比这更多的功能.您应该查看react-async文档以获取其功能的完整列表,并更详细地解释我上面简要描述的那些.
| 归档时间: |
|
| 查看次数: |
2242 次 |
| 最近记录: |