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

Dispatch multiple async actions with Redux Toolkit

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

我使用这个设置已经有一段时间了,没有出现任何并发症,因为我的功能很简单(比如 user/auth、购物车、类别和产品减速器)。

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

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;
  }
};

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

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

  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();
  }, []);
}

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

谢谢。

您不需要 await dispatch。你也不需要 try/catch 块,因为 thunk 会捕获任何 API 错误并发送一个“被拒绝”的动作。你可以dispatch你的三个thunk。

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

我会把你的 thunk 和你的 reducer 写得简单得多。我会使用一种操作类型,让 catalogName 成为 payload 的一部分(您也可以从操作的 meta 属性 访问它)。您可以删除 thunk 中的整个 switch 块和相应的 case reducers。相反,您可以使用一个 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;
    }
  }
});