redux 为什么一个被中止的thunk没有被立即拒绝,我如何处理加载

ctrmrzij  于 2023-03-18  发布在  其他
关注(0)|答案(2)|浏览(129)

我尝试使用ReduxToolkit构建一个简单的用例:

  • 调度thunk
  • 显示装载机指示灯
  • 如果在最后一个thunk完成运行之前发生了什么情况,则中止thunk

我使用一个效果:

useEffect(() => {
    const runningThunk = dispatch(asyncThunk());
    return () => {
      runningThunk.abort();
    };
  }, [dispatch, count]);

和基本切片:

extraReducers: (builder) => {
    builder.addCase(asyncThunk.pending, (state) => {
      state.isLoading = true;
    });
    builder.addCase(asyncThunk.fulfilled, (state) => {
      state.isLoading = false;
    });
    builder.addCase(asyncThunk.rejected, (state) => {
      state.isLoading = false;
    });

当我运行这段代码时,abort被调用,然后钩子被重新运行,一个新的dispatch被调用。
但是redux的处理方式不同,在前一个thunk被拒绝之前,第二个thunk被调度,挂起的action被调度。
这导致我的加载指示器只在步骤1和步骤3之间显示,因为被拒绝的thunk重置了状态。
这是一个bug吗?如果这是需要的行为,我该如何处理我的问题?
当我们在thunk结束前更改计数器两次时,沙箱重现了该问题。
https://codesandbox.io/s/wonderful-chaum-stgsn

qxgroojn

qxgroojn1#

这是不可避免的。一个正在运行的thunk是异步的,中止它也是异步的。但是启动thunk是同步发生的。
如果您有这样的顾虑,您应该跟踪您的商店中最近启动的thunk的requestId,并且只在沿着与此requestId有关的操作时更新您的商店。
请参见createAsyncThunk API文档中的第一个示例

smtd7mpg

smtd7mpg2#

我最终简单地使用:

builder.addCase(asyncThunk.rejected, (state, { meta }) => {
   if (!meta.aborted) {
     state.isLoading = false;
   }
});

相关问题