在 Redux Reducer 中执行 Ajax Fetch?

Posted

技术标签:

【中文标题】在 Redux Reducer 中执行 Ajax Fetch?【英文标题】:Perform Ajax Fetch in a Redux Reducer? 【发布时间】:2018-01-12 18:38:50 【问题描述】:

我正试图集中精力访问 Redux actionCreators 中的状态;而是执行以下操作(在减速器中执行 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;
    

【问题讨论】:

【参考方案1】:

根据 redux 的指导方针。

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

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

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

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

    在这里,您需要从动作创建者中调度异步动作 为此使用“redux-thunk”或“redux-saga” 您可以访问状态并创建一些异步操作

例如在您的动作创建者内部(仅作为示例)

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

【讨论】:

非常感谢您和@Matthew 的澄清,你们俩说的都很有道理。我已经用 thunk 实现了异步操作;但是,我想不通的是,我如何进行 api 调用(获取),但是在获取时将状态中的数据添加到我的 POST 变量中?例如:一个 CSRF 令牌? @sammysaglam 您可以访问 action-creator 中的状态。【参考方案2】:

来自 redux 文档:

改变状态的唯一方法是发出一个动作,一个描述发生了什么的对象。 不要将 API 调用放入 reducer。 Reducer 只是纯粹的函数,它们接受前一个状态和一个动作,然后返回下一个状态。记得返回新的状态对象,而不是改变之前的状态。

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

查看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)))
    

【讨论】:

非常感谢您和@WitVault 的澄清,你们俩说的都很有道理。我已经用 thunk 实现了异步操作;但是,我无法弄清楚的是,我如何进行 api 调用(获取),但是在获取时将状态中的数据添加到我的 POST 变量中?例如:一个 CSRF 令牌? @sammysaglam 查看更新后的答案。您可以有第二个参数,即函数getState,它将返回基本状态对象。 成功了!惊人的!太感谢了!我花了一个小时想弄清楚这个!

以上是关于在 Redux Reducer 中执行 Ajax Fetch?的主要内容,如果未能解决你的问题,请参考以下文章

redux-thunk的理解

所有的 redux 动作都应该有相应的 reducer 吗?

React Native Redux Reducer 不工作

如何在react中用redux组织store?

如何在 Redux 中显示一个执行异步操作的模态对话框?

[Redux/Mobx] 在redux中,什么是reducer?它有什么作用?