Redux Toolkit中两类帖子页面是否需创建独立Slice?
关于Redux Toolkit Slice设计与状态管理的解答
一、是否需要拆分多个Slice?
不需要,单个Slice完全满足需求。
- 全部帖子和个人帖子都属于帖子领域的状态,逻辑上高度关联:创建、编辑、删除帖子后,需要同时更新全部帖子列表和个人帖子列表(你当前代码已经这么处理了),放在同一个Slice里能更方便地同步这两个数组的状态,避免跨Slice的状态同步逻辑。
- 你的现有实现思路是合理的,所有异步操作(获取、创建、编辑、删除)都围绕帖子展开,集中在一个Slice里更便于维护和理解。
二、是否需要独立的error和loading状态?
需要拆分独立的状态,当前统一的status和error会导致状态冲突。
问题所在
你现在用全局的status和error,会出现以下问题:
- 当同时发起“获取全部帖子”和“获取个人帖子”请求时,两个请求的loading状态会互相覆盖,UI无法准确显示哪个列表在加载。
- 如果其中一个请求失败,错误信息会被另一个请求的状态覆盖,导致UI显示错误的提示。
- 查看帖子详情时,也会干扰列表的loading/error状态。
修改建议
把状态拆分为对应每个数据模块的独立状态,示例如下:
const initialState = { posts: [], userPosts: [], detailedPost: {}, // 拆分独立的加载状态 allPostsStatus: 'idle', userPostsStatus: 'idle', detailedPostStatus: 'idle', // 拆分独立的错误信息 allPostsError: null, userPostsError: null, detailedPostError: null, toEditPostId: null, }; const postsSlice = createSlice({ name: 'posts', initialState, reducers: { /* 保持现有reducers不变 */ }, extraReducers(builder){ builder // 获取全部帖子 .addCase(fetchMemoryPosts.pending, (state,_)=>{ state.allPostsStatus = 'loading'; state.allPostsError = null; // 重置错误 }) .addCase(fetchMemoryPosts.fulfilled, (state, action)=>{ state.allPostsStatus = 'success'; state.posts = action.payload; }) .addCase(fetchMemoryPosts.rejected, (state, action)=>{ state.allPostsStatus = 'failure'; state.allPostsError = action.payload; }) // 获取个人帖子 .addCase(getUserMemoryPosts.pending, (state,_)=>{ state.userPostsStatus = 'loading'; state.userPostsError = null; }) .addCase(getUserMemoryPosts.fulfilled, (state, action)=>{ state.userPostsStatus = 'success'; state.userPosts = action.payload; }) .addCase(getUserMemoryPosts.rejected, (state, action)=>{ state.userPostsStatus = 'failure'; state.userPostsError = action.payload; }) // 获取帖子详情 .addCase(fetchPostDetails.pending, (state, _)=>{ state.detailedPostStatus = "loading"; state.detailedPostError = null; }) .addCase(fetchPostDetails.fulfilled, (state, action)=>{ state.detailedPostStatus = "success"; state.detailedPost = action.payload; }) .addCase(fetchPostDetails.rejected, (state, action)=>{ state.detailedPostStatus = "failure"; state.detailedPostError = action.payload; }) // 创建帖子 .addCase(createMemoryPost.fulfilled, (state, action)=>{ state.userPosts = state.userPosts.concat(action.payload); state.posts = state.posts.concat(action.payload); }) // 编辑、删除帖子的case同理调整,只更新列表数据即可 .addCase(patchMemoryPost.fulfilled, (state, action)=>{ const {_id} = action.payload; state.userPosts = state.userPosts.map((post)=> post._id === _id ? action.payload : post); state.posts = state.posts.map((post)=> post._id === _id ? action.payload : post); }) .addCase(deleteMemoryPost.fulfilled, (state, action)=>{ const {_id} = action.payload; state.userPosts = state.userPosts.filter((post)=> post._id !== _id); state.posts = state.posts.filter((post)=> post._id !== _id); }) } }); // 对应的selector也要更新 export const getAllPostsStatusSelector = (state) => state.posts.allPostsStatus; export const getAllPostsErrorSelector = (state) => state.posts.allPostsError; export const getUserPostsStatusSelector = (state) => state.posts.userPostsStatus; export const getUserPostsErrorSelector = (state) => state.posts.userPostsError; export const getDetailedPostStatusSelector = (state) => state.posts.detailedPostStatus; export const getDetailedPostErrorSelector = (state) => state.posts.detailedPostError; // ...其他原有selector保持不变
好处
- 每个数据模块的加载状态和错误信息完全独立,不会互相干扰,UI可以精准地为每个列表或详情页显示对应状态。
- 状态逻辑更清晰,后期维护时能快速定位到对应模块的状态变化。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

