REACT如何使用Redux和Axios(使用promise中间件)发出AJAX请求?

时间:2017-06-27 17:08:08

标签: reactjs promise redux axios

我有这个动作创作者:

export function getLevelsMap() {

const request = axios.get(`/api/levels`);

return {
    type: GET_LEVELS_MAP,
    payload: request
    }
}

和这个减速器

import { GET_LEVELS_MAP } from '../actions';

export default function (state = null, action) {
switch (action.type) {
    case GET_LEVELS_MAP:
        return action.payload.levels;
    default:
        return state;
}
}

AJAX请求应该返回给我:

{
"levels": [
{
  "_id": "5951b7f0600af549fb1d269a",
  "name": "College",
  "__v": 0,
  "subjects": [
    {
      "_id": "594891db1dbdf635ca3019ab",
      "name": "Maths",
      "__v": 0
    },
    {
      "_id": "5948920d1dbdf635ca3019ac",
      "name": "Biology",
      "__v": 0
    }
  ...

请求确实有效(我已经用PostMan测试过了)

现在,我正在使用reducer和action:

连接我的组件
function mapStateToProps(state) {
return {
    levels: state.levels
}
};

export default connect(mapStateToProps, { getLevelsMap })(ChooseSubject);

我在componentDidMount方法中获取数据(调用操作):

  componentDidMount() {
    if (!this.props.levels) {
        this.props.getLevelsMap();
    }
}

并尝试使用reducer:

getSubjects(level) {
    let levels = this.props.levels;

    if (levels) {
        for (var item of levels) {
            if (item.name === level) {
                return item;
            }
        }
    }

    return null;

}

这是我说我正在使用promise中间件的地方

const createStoreWithMiddleware = applyMiddleware(promise)(createStore);

ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
    <BrowserRouter>
        <Switch>
            <Route path="/" component={HomePage} />
        </Switch>
    </BrowserRouter>
</Provider>
, document.querySelector('.root'));

但是,this.props.levels未定义...... PS:如果我硬编码(复制粘贴我在subject_reducer中从postMan获得的结果)来自AJAX请求的答案,那么一切都有效。

非常感谢您的非常感谢:)

2 个答案:

答案 0 :(得分:2)

如前面的回答中所述,您的axios请求返回一个承诺而不是数据,因为您拥有的是未解决的承诺,从而导致您的道具不符合您的预期。

要回答你的问题,我认为你不需要使用redux-promise,而是使用redux-thunk。根据{{​​3}}答案,似乎redux-promise允许您的行为成为承诺,但redux-thunk允许您的行为成为您需要的功能。使用redux-thunk,您实际上可以解决承诺并将数据发送到您的减速器,而不像现在您的减速器正在承诺。

答案 1 :(得分:1)

您不是在等待axios完成通话。首先,我假设promise内的applyMiddleware类似于redux-thunk,你需要做异步操作。

您的动作创建者应如下所示:

export const getLevelsMap = () => {
    return function(dispatch) {
        axios.get(`/api/levels`)
            .then(result => {  
                dispatch({
                    type: GET_LEVELS_MAP,
                    payload: result.data
                });
            })
            .catch(err => console.log(err));
    }
}

或者,使用async并等待:

export const getLevelsMap = () => async dispatch => {
    try {
        let response = await axios.get(`/api/levels`);
        dispatch({
            type: GET_LEVELS_MAP,
            payload: result.data
        })
    } catch (err) {
        console.log(err);
    }
}