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

时间:2021-04-14 22:44:51

标签: reactjs react-native redux react-redux redux-toolkit

我正在使用 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
  }
});

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

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

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

谢谢。

1 个答案:

答案 0 :(得分:0)

您不需要httpClient await。您也不需要 dispatch/try 块,因为 thunk 会捕获任何 API 错误并分派“被拒绝”的操作。你可以catch你的三个重击。

dispatch

我会把你的 thunk 和你的 reducer 写得更简单。我会使用一种操作类型并让 useEffect(() => { dispatch(catalogRequest("catalogOne")); dispatch(catalogRequest("catalogTwo")); dispatch(catalogRequest("catalogThree")); }, []); 成为 catalogName 的一部分(您也可以从操作的 payload 属性访问它)。您可以删除 thunk 中的整个 meta 块和相应的 case reducer。相反,您可以使用一个 case reducer 根据 switch 更新状态中的正确属性。

惊呼:

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