如何使用react-redux存储与异步HTTP请求

时间:2016-05-11 18:09:18

标签: javascript reactjs redux react-redux

我正在尝试使用AJAX调用更新带有数字的div。这是小部件:

import {store} from './Store';

class Widget extends React.Component {
    constructor(props) {
        super(props);
    }
    componentWillMount() {
        let req = function() {
            let xhr = new XMLHttpRequest();
            xhr.open('GET', this.props.apiUrl, true);
            xhr.onreadystatechange = function() {
                if (xhr.readyState === 4) {
                    if (xhr.response) {
                        store.dispatch({
                            type: 'SET_STATE',
                            state: {
                                foo: JSON.parse(xhr.response)
                            }
                        });
                    }
                }
            }.bind(this);
            xhr.send();
        }
        req.call(this);
    }
    render() {
        return(
            <widget>
                <div>{this.props.foo}</div>
            </widget>
        );
    }
}

继承人“减速器”:

import {List, Map} from 'immutable';
export default function(state = Map(), action) {
    switch(action.type) {
        case 'SET_STATE':
            return state.merge(action.state);
    }
    return state;
}

这是商店:

import {createStore} from 'redux';
import reducer from '../reducer';

export const store = createStore(reducer);

当我运行此代码时,我会加载页面,但foo未定义。请求返回包含正确数据的响应。正确调用dispatch()。如何异步触发在整个应用程序中传播的状态更改?

注意

请,请不要转发给详细的摘要博客文章,例如thisthis。我需要一个实际的代码示例,它使用store.dispatch()触发状态更改。感谢。

2 个答案:

答案 0 :(得分:0)

正如Azium在评论中提到的那样,你不需要使用redux-thunk来做到这一点,不过这就是你想要的。

您将redux-thunk中间件应用于商店:

var thunk = require('redux-thunk');
const store = createStore(
    combineReducers({
        reducer1,
        reducer2
    }),
    applyMiddleware(thunk)
);

然后你可以定义这样的动作:

export const getData = () => {
    return (dispatch) => {
        return fetch('/foo')
            .then((response) => response.json())
            .then((json) => dispatch(receieveData(json)));
    };
};

其中receieveData是您定义的另一个操作。

现在您可以在componentWillMount中调用此操作。我可能错过了一些东西,但这就是它的要点。这一切都在您原始帖子的第一个链接中(http://redux.js.org/docs/advanced/AsyncActions.html)。

编辑:当然,正如许多人已经说过的那样,你需要react-redux:)

答案 1 :(得分:0)

我发现了什么问题。我没有设置初始状态。

// Store.jsx

import {fromJS} from 'immutable';
import {createStore} from 'redux';
import reducer from '../reducer';

export const store = createStore(reducer);
store.dispatch({
    type:'SET_STATE',
    state: fromJS({
        foo: 0
    })
})

如果没有这个,更新的状态始终为null。这个简单的事实并不在任何官方的React / Redux文档中。