export const getPosts = () => dispatch => {
dispatch(setPostLoading());
axios
.get('/api/posts')
.then(res => {
dispatch({
type: GET_POSTS,
payload: res.data
})}
)
.catch(err =>
dispatch({
type: GET_POSTS,
payload: null
})
);
};
export const addLike = id => dispatch => {
axios
.post(`/api/posts/like/${id}`)
.then(res => {
dispatch(getPosts())
})
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
})
);
};
在我的项目中,每当用户单击帖子的点赞按钮时,都会使用该帖子的 id 调用
addLike
函数。
如果我正确理解你的问题,你是在问为什么你必须首先dispatch你的操作,然后在异步操作中再次需要dispatch进一步的操作。
这里的调度工作如何?
您首先通过调用
addLike
操作创建者并将返回的“值”分派到商店,将您的操作“值”分派到商店。
dispatch(addLike("123"));
通常,动作创建者返回一个动作对象,例如一个 Javascript 对象,具有
type
和 payload
属性。
{
type: "MY_AWESOME_ACTION",
payload: "This is my awesome payload value!",
}
但是,
addLike
在调用时会返回一个函数,例如addLike("123")
返回:
(dispatch) => {
axios
.post(`/api/posts/like/${id}`) // "/api/posts/like/123"
.then(res => {
dispatch(getPosts());
})
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
});
);
};
换句话说,以下两个代码片段在求值时是相同的。
dispatch(addLike("123"));
dispatch((dispatch) => {
axios
.post("/api/posts/like/123")
.then(res => {
dispatch(getPosts());
})
.catch(err =>
dispatch({
type: GET_ERRORS,
payload: err.response.data
});
);
});
Thunk,或异步操作创建者,返回 函数 而不是对象。您正在向商店派遣一个函数。
您在创建商店时添加到商店的 Thunk 中间件会拦截作为函数的操作,并等待它们解决(即解决或拒绝)。中间件调用此操作函数并将存储的
dispatch
函数(和 store.getState
以及 Thunk 中间件 extraArgument
)传递给它,以便可以根据需要调度进一步的操作。
这是一个非常棒的动画,可以帮助可视化异步数据流,借用自 Redux 文档。
Thunk 示例:
const someAsyncAction = (arg) => (dispatch, getState, extraArgument) => {
...
}
请注意,有两个“调度”功能位置,一个位于 UI 中,另一个位于内部调度存储/中间件通道。
为什么 getPosts() 在调度括号内调用?
在返回的
addLike
操作中,您正在使用从 Thunk 中间件传递给它的 dispatch
函数来将其他操作分派到商店,例如dispatch(getPosts());
。
类似地
getPosts
是另一个异步操作创建者,返回一个函数,该函数将从 Thunk 中间件传递给 dispatch
函数。
dispatch(getPosts());
评估为
dispatch((dispatch) => {
dispatch(setPostLoading());
axios
.get('/api/posts')
.then(res => {
dispatch({
type: GET_POSTS,
payload: res.data
})}
)
.catch(err =>
dispatch({
type: GET_POSTS,
payload: null
})
);
});