React如何处理组件之间异步的action
假设有这样一种情况,A,B之间通过flux共享数据,A先通过ajax获取异步数据,render完成后在把数据传递给B,B再进行render。
总体来说,在react components中处理ajax数据通信的问题,可以先用promise封装一个ajax通用方法。promise相当于为异步操作的结果准备的一个占位符,他有三种状态:pending/fulfiiled/rejected, 所有的promise 对象都有then方法,你可以从中操作成功或失败后的action。在componentDidMount中触发promise在then方法获取数据之后,做一个dispatch,然后setState ComponentA,dispatch给store后,trigger change事件然后在ComponentB的监听事件中setState 从而更新ComponentB。
下面会举一个简单的例子
1 test.json
{
"message": "done"
}
2 testAjax-store.js
import MicroEvent from '../utils/microevent';
import Dispatcher from '../dispatcher/dispatcher';
let testAjaxStore = {
message: 'start'
};
MicroEvent.mixin( testAjaxStore );
testAjaxStore.dispatchToken = Dispatcher.register(payload => {
switch (payload.actionType) {
case "ajaxAction":
testAjaxStore.message = payload.content;
testAjaxStore.trigger('change');
break;
}
});
export default testAjaxStore;
3 testAjax.js (简单来写,我把两个view写在了一起)
import React from 'react';
import ReactDOM from 'react-dom';
import $ from 'jquery';
import Dispatcher from './dispatcher/dispatcher';
import AjaxStore from './stores/testAjax-store';
//先用promise封装一个ajax通用方法
function getAjax(url, data = '' ){
return new Promise( (resolve, reject) => {
$.ajax({
url: url,
type: 'get',
dataType: 'json',
data: data,
})
.done(function(data) {
resolve(data);
})
.fail(function(error) {
reject(error);
});
})
};
class ComponentA extends React.Component {
constructor(props) {
super(props);
this.state = {
message: AjaxStore.message
};
}
componentDidMount() {
//获取数据之后,做一个dispatch,然后setState ComponentA
getAjax('./test.json').then( (data) => {
Dispatcher.dispatch({
actionType: 'ajaxAction',
content: data.message,
});
this.setState({'message': data.message})
});
}
render(){
return(
<h1>
{ this.state.message }
</h1>
)
}
}
class ComponentB extends React.Component {
constructor(props) {
super(props);
this.state = {
message: AjaxStore.message
}
}
componentDidMount(){
//监听事件中setState 从而更新ComponentB
AjaxStore.bind('change', ()=>{
this.setState({'message': AjaxStore.message})
});
}
render(){
return(
<h1>
{ this.state.message }
</h1>
)
}
}
class ComponentPage extends React.Component {
render(){
return(
<div>
<ComponentA />
<ComponentB />
</div>
)
}
}
ReactDOM.render(
<ComponentPage />,
document.getElementById('six')
);