使用 Redux Toolkit 调度多个异步操作

Posted

技术标签:

【中文标题】使用 Redux Toolkit 调度多个异步操作【英文标题】:Dispatch multiple async actions with Redux Toolkit 【发布时间】:2021-07-09 23:49:06 【问题描述】:

我正在使用 Expo/React Native 构建一个应用程序,并通过 Redux Toolkit 使用 Redux 来使用切片处理应用程序的存储/状态。

我已经使用这个设置有一段时间了,因为我的功能很简单(如用户/身份验证、购物车、类别和产品缩减器)。

但是对于这个应用程序,我需要从单个端点加载多个目录。为了实现这一点,我创建了一个“目录”切片,其中包含多个减速器和一个操作,它根据目录的名称执行请求并分派减速器。

const initialState = 
  catalogOne: [],
  catalogTwo: [],
  catalogThree: [],
  catalogN: []


const catalogsSlice = createSlice(
  name: "catalogs",
  initialState,
  reducers: 
    catalogOneRequestSucceeded: (state,action) => 
      state.catalogOne = action.payload
    ,
    catalogTwoRequestSucceeded: (state,action) => 
      state.catalogTwo = action.payload
    ,
    // ... and so on a reducer for each catalog
  
);

然后我有以下操作,用于请求具有目录名称的端点并调度减速器:

export const catalogRequest = (catalogName) => async (dispatch, getState) => 
  const state = getState();

  try 
    const rsp = await axios.get(`https://catalogEndpointBase/$catalogName`, 
      headers: 
        Authorization: `Bearer $state.user.accessToken`,
        "Content-Type": "application/json",
      ,
    );

    switch (catalogName) 
      case "catalogOne":
        dispatch(catalogOneRequestSucceeded(rsp.data));
        break;
      case "catalogTwo":
        dispatch(catalogTwoRequestSucceeded(rsp.data));
        break;
      case "catalogThree":
        dispatch(catalogThreeRequestSucceeded(rsp.data));
        break;
    

    return rsp.data;
   catch (e) 
    throw e;
  
;

所以我现在的问题是:如何以“异步/等待”方式多次分派此操作,以便一个接一个地加载目录?还有:我的做法是正确的还是有更好的方法来处理这种多重请求?

我在想这样的事情,但我真的不知道如何实现:

  useEffect(() => 
    const loadCatalogsAsync = async() => 
      try 
        await dispatch(catalogRequest("catalogOne"));
        await dispatch(catalogRequest("catalogTwo"));
        await dispatch(catalogRequest("catalogThree"));
        // ... and so on for all my catalogs
       catch ( e ) 
        console.error(e);
      
    

    loadCatalogsAsync();
  , []);

我们的目标是为应用在加载时需要获取多个数据的行为类型找到最佳实践。

谢谢。

【问题讨论】:

【参考方案1】:

您不需要await dispatch。您也不需要 try/catch 块,因为 thunk 将捕获任何 API 错误并调度“拒绝”操作。你可以只 dispatch 你的三个 thunk。

useEffect(() => 
  dispatch(catalogRequest("catalogOne"));
  dispatch(catalogRequest("catalogTwo"));
  dispatch(catalogRequest("catalogThree"));
, []);

我会更简单地编写你的 thunk 和 reducer。我会使用一种操作类型,让catalogName 成为payload 的一部分(您也可以从操作的meta 属性访问它)。您可以在您的 thunk 和相应的 case reducer 中删除整个 switch 块。相反,您可以使用一个 case reducer,根据 action.payload.catalogName 更新状态中的正确属性。

重击:

export const catalogRequest = createAsyncThunk(
  "catalogs/request",
  async (catalogName,  getState ) => 
    const state = getState();
    const rsp = await axios.get(`https://catalogEndpointBase/$catalogName`, 
      headers: 
        Authorization: `Bearer $state.user.accessToken`,
        "Content-Type": "application/json"
      
    );
    return 
      data: rsp.data,
      catalogName
    ;
  
);

切片:

const catalogsSlice = createSlice(
  name: "catalogs",
  initialState,
  reducers: ,
  extraReducers: 
    [catalogRequest.fulfilled]: (state, action) => 
      const  data, catalogName  = action.payload;
      state[catalogName] = data;
    
  
);

【讨论】:

以上是关于使用 Redux Toolkit 调度多个异步操作的主要内容,如果未能解决你的问题,请参考以下文章

在 Redux 中链接多个异步调度

Redux工具包 - Redux Toolkit的异步操作(发送网络请求)

Redux ToolKit:是不是可以在由 createAsyncThunk 创建的一个操作中调度来自同一切片的其他操作

在 redux 中在哪里调度多个操作?

使用 typescript 将异步操作发送到 redux 调度

Redux-Toolkit createAsyncThunk with Typescript