使用Redux Toolkit调用TMDB API获取全类型电影遇单类型返回问题求助
问题:Redux Toolkit调用TMDB API获取全分类电影的问题
我正在尝试用Redux Toolkit调用TMDB API,获取所有电影类型下的全部电影。我写了循环发起API请求,原本想把所有电影都存入Movies数组,但现在循环只能返回第一个类型的电影。我的目标是让dataMovieGenres收集到所有电影数据,在extraReducers里处理后,能遍历展示所有分类的电影。另外我需要一种不用push(避免副作用)的方式,把Axios返回的所有数据存入数组并返回。
当前代码
初始状态
const initialState = { Most_Popular: [], // 首页展示的热门电影列表 top_rated: [], // 首页展示的高分电影列表 Movies: [], // 所有电影列表 Movie: {}, // 当前选中的电影 isLoading: true, // 检查页面是否加载中 isError: false, };
获取分类电影的异步Thunk
export const getMoviesGenres = createAsyncThunk( "getMoviesGenres", async (_, thunkAPI) => { try { const api = `api_key=${process.env.REACT_APP_KEY_API}`; const data = await getJSON.get(`genre/movie/list?${api}`); // 获取所有类型ID for (let i = 0; i <= data.data.genres.length; i++) { if (!data.data.genres[i]) return; // 守卫语句 const { id, name } = data.data.genres[i]; const dataMovieGenres = [ await getJSON.get(`discover/movie?${api}&with_genres=${id}`) ]; return dataMovieGenres; } } catch (error) { return thunkAPI.rejectWithValue(error); } } );
Reducer处理逻辑
// 获取分类电影 builder .addCase(getMoviesGenres.pending, (state) => { state.isLoading = true; state.isError = false; }) .addCase(getMoviesGenres.fulfilled, (state, { payload }) => { console.log(payload); // state.Movies = payload.data.results; state.isLoading = false; state.isError = false; }) .addCase(getMoviesGenres.rejected, (state, { payload }) => { state.isLoading = false; state.isError = false; toast.error(payload.message); });
问题原因
- 循环内的
return dataMovieGenres会直接终止函数,导致仅执行第一次循环就返回第一个分类的数据。 - 循环条件
i <= data.data.genres.length会触发最后一次循环时data.data.genres[i]为undefined,触发守卫语句直接return。
解决方法
使用map生成所有请求的Promise,再配合Promise.all并行处理所有请求,既无副作用又能收集全部数据:
修改后的异步Thunk
export const getMoviesGenres = createAsyncThunk( "getMoviesGenres", async (_, thunkAPI) => { try { const api = `api_key=${process.env.REACT_APP_KEY_API}`; const genresRes = await getJSON.get(`genre/movie/list?${api}`); const genres = genresRes.data.genres; // 用map生成请求Promise数组,Promise.all等待全部完成 const allMoviesData = await Promise.all( genres.map(async ({ id, name }) => { const movieRes = await getJSON.get(`discover/movie?${api}&with_genres=${id}`); // 返回包含分类名称和对应电影的对象,方便后续展示 return { genreName: name, movies: movieRes.data.results }; }) ); return allMoviesData; } catch (error) { return thunkAPI.rejectWithValue(error); } } );
修改后的Reducer处理
builder .addCase(getMoviesGenres.pending, (state) => { state.isLoading = true; state.isError = false; }) .addCase(getMoviesGenres.fulfilled, (state, { payload }) => { // payload是包含所有分类及对应电影的数组,直接赋值 state.Movies = payload; state.isLoading = false; state.isError = false; }) .addCase(getMoviesGenres.rejected, (state, { payload }) => { state.isLoading = false; state.isError = true; // 标记错误状态 toast.error(payload.message); });
说明
Promise.all并行处理请求,比串行循环效率更高。- 返回的每个对象包含分类名称和对应电影列表,后续展示时可直接遍历
Movies数组按分类渲染。 - 通过
map生成新数组,完全避免了push带来的副作用。
内容的提问来源于stack exchange,提问作者Daniel Barda
相关产品推荐
相关产品推荐

