首页 文章

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

提问于
浏览
1

我有这个动作创作者:

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 回答

  • 1

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

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

  • 2

    你不是't waiting for axios to complete the call. First, I'假设 applyMiddleware 里面的 promise 类似于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);
        }
    }
    

相关问题