想象一下,我有一个非常简单的React组件,它显示了this.state.myList
中存储的元素列表(参见下面的示例)
点击底部的“刷新”按钮会使React查询后端服务器并检索随后将显示的更新列表。该列表的实际内容或实现是无关紧要的。
var Foo = React.createClass({
handleButtonClick: function() {
return $.ajax({
type: "POST",
url: "/some/refresh/url",
data: JSON.stringify({}),
dataType: "json",
contentType: "application/json",
success: (function(response){
self.setState({ myList: response.list });
})
});
},
render: function() {
return (
<div className="container">
<ul>
{
this.state.myList.map(function(item) {
return <li id="{item.id}">{item.name}</li>
});
}
</ul>
<input type="submit" value="REFRESH LIST" onClick={this.handleButtonClick} />
</div>
);
}
});
假设AJAX调用(无论出于何种原因)需要几秒钟。在此期间,我希望展示一个标准的“加载”或“旋转器”gif,让用户知道它正在工作。
这样做的最佳方法是什么?
在AJAX调用之前,我可以手动更新DOM并插入一个微调器gif,但这似乎不是“React方式”。而且我不知道对反应维持的ReactDOM会产生什么影响。
我可以跟踪isLoading
的状态,并在加载时显示微调器而不是列表。但后来我需要render()
某事,然后立即启动另一个AJAX动作调用。
任何帮助表示感谢。
谢谢!
答案 0 :(得分:9)
我总能解决这个问题的方法是让组件在其状态下跟踪fetchInProgress
。
在进行提取之前,请将此值设置为true
;当提取完成(成功或失败)时,您将值设置回false
。
组件的render
方法然后尊重这个标志;如果标志为true
,则呈现微调器而不是数据集。
var Foo = React.createClass({
handleButtonClick: function() {
// before making call, set fetch flag
self.setState({ fetchInProgress: true });
return $.ajax({
type: "POST",
url: "/some/refresh/url",
data: JSON.stringify({}),
dataType: "json",
contentType: "application/json",
success: (function(response) {
// when updating with dataset, also reset fetch flag
self.setState({
fetchInProgress: false,
myList: response.list
});
}),
failure: ((function(reason) {
// make sure to reset even if fetch fails!
self.setState({
fetchInProgress: false
});
})
});
},
render: function() {
return (
<div className="container">
<ul>
{
this.state.fetchInProgress
: <Spinner />
: this.state.myList.map(function(item) {
return <li id="{item.id}">{item.name}</li>
})
}
</ul>
<input type="submit" value="REFRESH LIST" onClick={this.handleButtonClick} />
</div>
);
}
});
答案 1 :(得分:4)
React模型是以UI作为您所在州的代表而构建的。这意味着您应该将状态建模为“必要数据是什么”,isLoading
的返回值就是您显示数据的方式。
在您的情况下,您应该跟踪render()
并在var Foo = React.createClass({
getInitialState: function() {
return {isLoading: false};
},
handleButtonClick: function() {
this.setState({ isLoading: true });
return $.ajax({
type: "POST",
url: "/some/refresh/url",
data: JSON.stringify({}),
dataType: "json",
contentType: "application/json",
success: (function(response){
self.setState({ myList: response.list, isLoading: false });
})
});
},
render: function() {
return (
<div className="container">
<ul>
{
this.state.myList.map(function(item) {
return <li id="{item.id}">{item.name}</li>
});
}
</ul>
{this.state.isLoading && <Spinner />}
<input type="submit" value="REFRESH LIST" onClick={this.handleButtonClick} />
</div>
);
}
});
中根据您所在州的值有条件地显示微调器。
depends_on:
kafka:
condition: service_healthy
答案 2 :(得分:2)
render: function() {
return (
<div className="container">
<ul>
{
this.state.fetchInProgress ?
<Spinner />
:
this.state.myList.map(function(item) {
return <li id="{item.id}">{item.name}</li>
})
}
</ul>
<input type="submit" value="REFRESH LIST" onClick={this.handleButtonClick} />
</div>
);
}