Redux Toolkit Thunk difference

huangapple go评论65阅读模式
英文:

Redux Toolkit Thunk difference

问题

使用createAsyncThunk和async + dispatch两种方式处理Redux Toolkit中的thunk有什么区别?

创建使用createAsyncThunk的thunk函数时,您可以定义一个名为"yourSlice/deleteColumnAndTasks"的动作类型,并使用async函数来执行异步操作。createAsyncThunk会自动处理异步操作的状态管理,包括请求、成功和失败等情况。它提供了一种更加抽象和自动化的方式来处理异步操作,使您的代码更加简洁和可维护。

另一方面,使用async + dispatch方式,您需要手动管理异步操作的状态。您将传递dispatch函数,并在内部使用try-catch块来处理错误情况。这种方式更加手动,您需要自己处理异步操作的各个阶段,并在错误处理方面具有更多的控制权。

总结来说,createAsyncThunk提供了一种更加抽象和自动化的方式来处理异步操作,而async + dispatch方式则更加手动,您需要更多的自定义控制。选择哪种方式取决于您的项目需求和个人偏好。

英文:

I was searching about thunks on Redux-toolkit and I found 2 ways of dealing with them:

createAsyncThunk or just using async + dispatch

Using createAsyncThunk:

export const deleteColumnAndTasks = createAsyncThunk(
  'yourSlice/deleteColumnAndTasks',
  async ({ boardId, column }) => {
    const tasksToDelete = column.taskIds || [];
    await changeBoardColumns({
      operationType: 'delete',
      targetBoardId: boardId,
      columnId: column.id
    });
    await deleteColumn({ columnId: column.id });
    await Promise.all(tasksToDelete.map(taskId => deleteTask({ taskId })));
  }
);

Using async + dispatch

export const deleteColumnAndTasks = ({ boardId, column }) => async dispatch => {
  const tasksToDelete = column.taskIds || [];
  try {
    await dispatch(changeBoardColumns({
      operationType: 'delete',
      targetBoardId: boardId,
      columnId: column.id
    }));
    await dispatch(deleteColumn({ columnId: column.id }));
    await Promise.all(tasksToDelete.map(taskId => dispatch(deleteTask({ taskId }))));
  } catch (error) {
    console.log('Error deleting column and tasks', error);
  }
};

What is the difference between the two ways?

答案1

得分: 1

它们都旨在分派操作以更改存储状态。它们都将返回一个 Promise 对象,正如所述。这就是它们的相似之处。

createAsyncThunk() 是一个工厂,用于注册并返回一个函数(操作创建器),该函数将在将来被调用,并且设计用于返回一个 Promise 对象。文档中说明

它基于传递的操作类型前缀生成 Promise 生命周期操作类型,并返回一个 thunk 操作创建器,该操作创建器将运行 Promise 回调并基于返回的 Promise 分派生命周期操作。

此外,文档中提到的生命周期操作

createAsyncThunk 将使用 createAction 生成三个 Redux 操作创建器:pendingfulfilledrejected。每个生命周期操作创建器都将附加到返回的 thunk 操作创建器上,以便您的减速器逻辑可以引用操作类型并在分派时响应操作。每个操作对象将在 action.meta 下包含当前的唯一 requestId 和 arg 值。

因此,如果重要的设计选择是跟踪/监视/订阅您正在分派的异步操作,createAsyncThunk() 为您提供了无需额外努力即可完成所有这些操作的方法。

例如,在 createSlice() 调用中,可以执行以下操作:

extraReducers: builder => {
  builder
    .addCase(deleteColumnAndTasks.pending, (state, action) => {
      // 执行 pending 操作
    })
    .addCase(deleteColumnAndTasks.fulfilled, (state, action) => {
        state.value = [action.payload, ...state.value];
    })
    // 等等。
})

第二个示例只是一个在调用时同步执行的函数,它使用柯里化来传递 boardIdcolumndispatch 函数的引用。createAsyncThunk() 自动提供的所有工具都不存在。如果需要这些功能,将需要单独编写它们。

英文:

They both are designed to dispatch actions to change the state of the store. They both will return a Promise object as written. That is where the similarities end.

createAsyncThunk() is a factory that registers and returns a function (action creator) that will be called in the future and that is designed to return a Promise object. The docs state:

> It generates promise lifecycle action types based on the action type
> prefix that you pass in, and returns a thunk action creator that will
> run the promise callback and dispatch the lifecycle actions based on
> the returned promise.

Also Life Cycle Actions from the docs

> createAsyncThunk will generate three Redux action creators using
> createAction: pending, fulfilled, and rejected. Each lifecycle action
> creator will be attached to the returned thunk action creator so that
> your reducer logic can reference the action types and respond to the
> actions when dispatched. Each action object will contain the current
> unique requestId and arg values under action.meta.

So if it is an important design choice to keep track/monitor/subscribe to the async actions you are dispatching, createAsyncThunk() provides you the means to do all of that with no extra effort on your own.

For example, in a createSlice() call one can do something like this:

<!-- language: lang-js -->

extraReducers: builder =&gt;
  builder
    .addCase(deleteColumnAndTasks.pending, (state, action) =&gt; {
      // do pending action
    })
    .addCase(deleteColumnAndTasks.fulfilled, (state, action) =&gt; {
        state.value = [action.payload, ...state.value];
    })
    // etc.
)

<!-- end snippet -->

One other important capability that createAsyncThunk() provides is the ability to easily cancel the async action based upon a user defined condition.

=====

The second example is simply a synchronously executed (at call time) function that uses currying to pass in boardId, column and a reference the to dispatch function. All of the tooling provided automagically by createAsyncThunk() does not exist. Those features, if required will need to be written separately.

huangapple
  • 本文由 发表于 2023年3月7日 09:45:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/75657344.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定