我在我的项目中使用 redux 和 saga,在商店中发出 Axios 请求。
为了向用户提供有关请求是否成功的反馈,我在我的存储中存储了一个对象,该对象包含两个属性 - errMsg
和 isFetching
。
每当我提出请求时,我都会将 isFetching
设置为 true,然后如果我的请求成功,我就会触发一个成功操作,将 isFetching
更改为 false。
我在我的组件中监听 isFetching
的变化,如果 isFetching
的最后一个状态是假的,现在它变成了真,并且没有错误消息,那么我会触发一个成功模式。
这个实现对我来说是一个 POST 请求,但是当我用一个 DELETE 请求尝试它时,isFetching
从未改变为 true。
我尝试调试 redux,发现两个动作都在发生,store 也在变化,但是我的组件中的效果没有被触发。
我在将 isFetching
更改为 true 之间添加了一个延迟,然后它起作用了。
Redux 更改太快以至于 useSelector 无法获取更改? 有解决办法吗?
(不好意思解释一下代码,我的项目在封闭的网络中,这里不能复制代码,如果解释的不够好,请告诉我,我会尝试手动编写代码)
编辑:
添加代码示例:
isFetching
中变化的监听器:
const { isFetchingDelete, errMsgDelete } = useSelector(
(state: StoreState) => ({
isFetchingDelete: state.students.deleteState.isFetching,
errMsgDelete: state.students.deleteState.errMsg,
})
);
const prevIsFetchingDeleteRef = useRef<boolean>();
.........
useEffect(() => {
// trying to log the value of isFetchingDelete here, always logs false
if (!isFetchingDelete && prevIsFetchingDeleteRef.current) {
if (errMsgDelete) {
Swal.fire();
} else {
Swal.fire();
}
}
prevIsFetchingDeleteRef.current = isFetchingDelete;
}, [errMsgDelete, isFetchingDelete]);
传奇:
function* deleteStudentHandler(action: ActionType<typeof deleteStudent>) {
try {
yield call(StudentsService.delete, action.payload);
// if I add a delay of 1000ms here it's working
yield put(deleteStudentSuccess(action.payload));
} catch (e) {
yield put(deleteStudentFailure(e.message));
}
}
我的减速器:
case: StudentsActionTypes.DELETE_STUDENT: {
return {
...state,
deleteState: {
...state.deleteState,
isFetching: true
}
}
}
case: StudentsActionTypes.DELETE_STUDENT_SUCCESS: {
return {
...state,
students: [
...state.students.filter((student) => student.id !== action.payload),
],
deleteState: {
...state.deleteState,
isFetching: false,
}
}
}
上面的代码在需要 300 毫秒的 post 请求上工作得很好,但在需要 2 毫秒(json-server)的删除请求上它不起作用。 添加我在代码中的注释中声明的位置,使代码工作。
答案 0 :(得分:0)
我终于明白为什么会这样了。
在这里,我的问题是 StudentService.delete 没有返回 Axios 响应,因此没有返回承诺,并且 saga 没有什么可等待的..
function* deleteStudentHandler(action: ActionType<typeof deleteStudent>) {
try {
yield call(StudentsService.delete, action.payload);
// if I add a delay of 1000ms here it's working
yield put(deleteStudentSuccess(action.payload));
} catch (e) {
yield put(deleteStudentFailure(e.message));
}
}
希望这能帮助其他可能遇到此问题的人。