在Redux Reducer中执行Ajax Fetch?

时间:2017-08-04 18:26:04

标签: redux redux-thunk

我正试图绕过Redux actionCreators中的状态;而是执行以下操作(在reducer中执行ajax操作)。为什么我需要为此访问状态 - 因为我想使用存储在状态中的CSRF令牌执行ajax。

有人可以告诉我以下是否被认为是不良做法/反模式?

export const reducer = (state = {} , action = {}) => {

    case DELETE_COMMENT: {

        // back-end ops
        const formData = new FormData();
        formData.append('csrf' , state.csrfToken);
        fetch('/delete-comment/' + action.commentId , {
            credentials:'include' ,
            headers:new Headers({
                'X-Requested-With':'XMLHttpRequest'
            }) ,
            method:'POST' ,
            body:formData
        })

        // return new state
        return {
            ...state ,
            comments:state.comments.filter(comment => comment.id !== action.commentId)
        };
    }

    default: {
        return state;
    }
}

2 个答案:

答案 0 :(得分:7)

来自redux文档:

  

改变状态的唯一方法是发出一个动作,一个描述发生的事情的对象。 不要将API调用放入reducers。 Reducers只是纯函数,它采用先前的状态和动作,并返回下一个状态。记住要返回新的状态对象,而不是改变以前的状态。

行动应描述变化。因此,该操作应包含新版本状态的数据,或者至少指定需要进行的转换。因此,API调用应该进入异步操作,以分派操作来更新状态。减速器必须始终是纯净的,没有副作用。

查看async actions了解详情。

redux示例中的异步操作示例:

function fetchPosts(subreddit) {
    return (dispatch, getState) => {
        // contains the current state object
        const state = getState();

       // get token
       const token = state.some.token;

        dispatch(requestPosts(subreddit));

        // Perform the API request
        return fetch(`https://www.reddit.com/r/${subreddit}.json`)
            .then(response => response.json())

            // Then dispatch the resulting json/data to the reducer
            .then(json => dispatch(receivePosts(subreddit, json)))
    }
}

答案 1 :(得分:4)

根据redux指南。

减速机保持纯净非常重要。你应该在减速机内做的事情:

  • 改变其论点;
  • 执行API调用和路由转换等副作用;
  • 调用非纯函数,例如Date.now()或Math.random()。

如果你问它是否是反模式,那么它是绝对的。

但是如果你问什么是解决方案。

  1. 您需要从动作创建者
  2. 发送异步动作
  3. 使用“redux-thunk”或“redux-saga”作为
  4. 您可以访问状态并创建一些异步操作
  5. 例如在你的动作创作者(仅举例)中

    export function deleteCommment(commentId) {
        return dispatch => {
            return Api.deleteComment(commentId)
                .then( res => {
                    dispatch(updateCommentList(res));
                });
        };
    }
    
    export function updateCommentList(commentList) {
        return {
            type : UPDATE_COMMENT_LIST,
            commentList
        };
    }
    

    编辑:您可以访问状态 -

    export function deleteCommment(commentId) {
        return (dispatch, getState) => {
            const state = getState();
            // use some data from state
            return Api.deleteComment(commentId)
                .then( res => {
                    dispatch(updateCommentList(res));
                });
        };
    }