我正在使用React + Redux的Web应用程序,后端使用Django(DRF)。我正在使用axios发送我的API请求,这是异步的。我现在面临的问题是,在分派下一个动作之前,分派的动作不会等待API调用完成。下面是我的代码
const mapDispatchToProps = dispatch => ({
success: id => {
dispatch(fetchSalesProject(id));
dispatch(createMessage('Requirement successfully updated!'))
}
})
fetchSalesProject操作(axiosInstance只是对axios调用的自定义修改,功能相同)
export const fetchSalesProject = (id) => (dispatch) => {
console.log('enter sales project action')
axiosInstance
.get(`/sales-project/detail/${id}/`)
.then((res) => {
console.log('fetched data')
dispatch({
type: FETCH_SALES_PROJECT,
payload: res.data,
});
})
.catch((err) => dispatch(returnErrors(err.response.data, err.response.status)));
};
createMessage操作
export const createMessage = (message) => {
console.log('message')
return {
type: CREATE_MESSAGE,
message: message,
};
};
在调用this.props.success(请参阅mapDispatchToProps)时,会在接收到api调用响应数据之前显示该消息(通过console.log('message')在console.log('fetched之前运行)这一事实可以看出数据”)
在运行createMessage操作之前,我希望从api调用中获取数据,是否有关于如何完成此操作的建议?我是React的新手,尤其是Redux,所以希望你们能为我指出正确的方向。
此外,我是否可以检查在mapDispatchToProps中进行分派以及在操作内进行分派是否错误(请参阅fetchSalesProject操作)。它会引起性能问题还是会皱眉呢?请告诉我,因为我对Redux感到很困惑。
感谢大家通读,感谢所有帮助:-)
答案 0 :(得分:2)
从UI分发时,您只是向reducer发送一个对象,该对象将依次减少商店的状态,并在流程结束时重新呈现引用已更改道具的组件。在分派第一个动作的那一刻,没有任何东西告诉组件在将下一个对象发送给reducer之前应该等待的组件
所以您有2个选择,
第一个操作是在UI本身上,使用componentDidUpdate
或useEffect
可以在第一个操作减少后运行第二个操作
componentDidUpdate(prevProps) {
if (prevProps.salesProject != this.props.salesProject)
dispatch(createMessage('Requirement successfully updated!'))
}
而我假设dispatch(fetchSalesProject(id));
修改了salesProject
属性
另一种方法是,如果您实际上对message
和salesProject
感到满意,可以将它们归还给reducer,那就是将它们分派到一个动作中
export const fetchSalesProjectAndMessage = (id, message) => (dispatch) => {
console.log('enter sales project action')
axiosInstance
.get(`/sales-project/detail/${id}/`)
.then((res) => {
console.log('fetched data')
dispatch({
type: FETCH_SALES_PROJECT_AND_MESSAGE,
payload: { data: res.data, message }
});
})
.catch((err) => dispatch(returnErrors(err.response.data, err.response.status)));
};
在减速器payload.data
上,payload.message
都将引用所需的信息
答案 1 :(得分:2)
有一个更好的方法可以执行此操作,该方法不会强制您组合两个动作创建者。当重击动作创建者返回承诺时,您可以等待它。您当前的代码未返回axios承诺,但是如果您返回了它,则可以执行以下操作:\
const mapDispatchToProps = (dispatch) => ({
success: (id) => {
dispatch(fetchSalesProject(id)).then(() =>
dispatch(//wait for fetchSalesProject to finish
createMessage('Requirement successfully updated!')
)
);
},
});
export const fetchSalesProject = (id) => (dispatch) => {
console.log('enter sales project action');
return axiosInstance //you did not return anything here
.get(`/sales-project/detail/${id}/`)
.then((res) => {
console.log('fetched data');
dispatch({
type: FETCH_SALES_PROJECT,
payload: res.data,
});
})
.catch((err) => {
dispatch(
returnErrors(err.response.data, err.response.status)
);
//return rejected promise here
return Promise.reject(err);
});
};