天行健, 君子以自强不息
Sunny's Blog
Title

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')
                );
            
地势坤,君子以厚德载物