我正在使用Expo/React Native构建一个应用程序,并通过Redux Toolkit使用Redux来处理使用切片的应用程序的存储/状态。
我已经使用这个设置一段时间了,没有复杂的问题,因为我的功能很简单(比如user/auth、cart、category和products reducers(。
但对于这个应用程序,我需要从一个端点加载多个目录。为了实现这一点,我创建了一个";目录";具有多个reducer和一个操作的slice,该操作根据目录的名称执行请求和调度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
}
});
然后我有以下操作,用于请求具有目录名称的端点并调度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();
}, []);
}
目标是为加载应用程序时需要应用程序获取多个数据的行为找到最佳实践。
谢谢。
您不需要await
和dispatch
。您也不需要try
/catch
块,因为thunk将捕获任何API错误并调度"拒绝"操作。你可以只dispatch
你的三个暴徒。
useEffect(() => {
dispatch(catalogRequest("catalogOne"));
dispatch(catalogRequest("catalogTwo"));
dispatch(catalogRequest("catalogThree"));
}, []);
我会把你的thunk和reducer写得简单得多。我将使用一种操作类型,并让catalogName
成为payload
的一部分(您也可以从操作的meta
属性访问它(。您可以删除thunk中的整个switch
块和相应的大小写减少器。相反,您可以使用一个大小写减少器来更新基于action.payload.catalogName
的状态中的正确属性。
thunk:
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;
}
}
});
我使用Promise.all((解决了这个问题。我需要等待所有初始任务完成,这些任务是异步操作,彼此不依赖,然后隐藏启动屏幕(使用RNBootSplash(:
useEffect(() => {
const runInitialTasks = async () => {
await Promise.all([dispatch(initGame()), dispatch(initOnboarding())]);
};
runInitialTasks().then(() =>
RNBootSplash.hide({fade: true, duration: 400}),
);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);