在 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 动作都应该有相应的 reducer 吗?