在 Redux Reducer 中执行 Ajax 提取?

Perform Ajax Fetch in a Redux Reducer?

我正试图集中精力访问 Redux actionCreators 中的状态;而是执行以下操作(在减速器中执行 ajax 操作)。为什么我需要为此访问状态 — 因为我想使用存储在状态中的 CSRF 令牌执行 ajax。

有人可以告诉我以下内容是否不好 practice/anti-pattern?

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;
    }
}

来自 redux 文档:

The only way to change the state is to emit an action, an object describing what happened. Do not put API calls into reducers. Reducers are just pure functions that take the previous state and an action, and return the next state. Remember to return new state objects, instead of mutating the previous state.

操作应描述更改。因此,动作应该包含新版本状态的数据,或者至少指定需要进行的转换。因此,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)))
    }
}

按照 redux 的指导方针。

reducer 保持纯净非常重要。你不应该在 reducer 中做的事情:

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

如果你问它是否是反模式,那么肯定是。

但是如果你问解决办法是什么

  1. 这里你需要从你的 action-creators 中调度 async-action
  2. 为此使用 "redux-thunk" 或 "redux-saga"
  3. 您可以访问状态并创建一些异步操作

例如在你的动作创建器中(仅举个例子)

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));
            });
    };
}