You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何构建包含重复嵌套切片的Redux + Redux Toolkit store

核心实现思路

你不需要修改原有三个子切片的内部逻辑,只需要把它们的reducer和初始状态导出,在blogsSlice中通过extraReducers的匹配器代理子切片的action,将对应博客下的子状态传入子reducer处理即可,具体实现如下:


1. 改造原有子切片,导出初始状态与reducer

把原有的postsSlice、commentsSlice、usersSlice的初始状态和reducer单独导出,不需要再注册到根reducer中,示例代码:

// postsSlice.js 示例,comments和users切片同理改造
import { createSlice } from '@reduxjs/toolkit'

// 单独导出初始状态
export const initialPostsState = {
  byId: {},
  allIds: []
}

const postsSlice = createSlice({
  name: 'posts',
  initialState: initialPostsState,
  reducers: {
    addPost: (state, action) => { 
      // 保留你原有逻辑不变
      const newPost = action.payload
      state.byId[newPost.id] = newPost
      state.allIds.push(newPost.id)
    },
    // 其他原有reducer逻辑保留
  }
})

export const { addPost } = postsSlice.actions
// 单独导出reducer
export const postsReducer = postsSlice.reducer

2. 定义blogsSlice

import { createSlice, createAction } from '@reduxjs/toolkit'
import { postsReducer, initialPostsState } from './postsSlice'
import { commentsReducer, initialCommentsState } from './commentsSlice'
import { usersReducer, initialUsersState } from './usersSlice'

// 定义新增博客的action
export const addBlog = createAction('blogs/addBlog', (blogId) => {
  return { payload: { blogId } }
})

const blogsSlice = createSlice({
  name: 'blogs',
  initialState: {
    byId: {},
    allIds: []
  },
  extraReducers: (builder) => {
    // 新增博客的逻辑,初始化对应博客下的三个子状态
    builder.addCase(addBlog, (state, action) => {
      const { blogId } = action.payload
      if (!state.byId[blogId]) {
        state.byId[blogId] = {
          posts: initialPostsState,
          comments: initialCommentsState,
          users: initialUsersState
        }
        state.allIds.push(blogId)
      }
    })
    // 匹配所有子切片的action,代理到对应博客的子状态处理
    .addMatcher(
      (action) => action.type.startsWith('posts/') || action.type.startsWith('comments/') || action.type.startsWith('users/'),
      (state, action) => {
        // 约定所有子操作的payload必须携带blogId参数,指定要操作的博客
        const { blogId } = action.payload
        const targetBlog = state.byId[blogId]
        if (!targetBlog) return

        // 调用对应子reducer处理子状态
        if (action.type.startsWith('posts/')) {
          targetBlog.posts = postsReducer(targetBlog.posts, action)
        } else if (action.type.startsWith('comments/')) {
          targetBlog.comments = commentsReducer(targetBlog.comments, action)
        } else if (action.type.startsWith('users/')) {
          targetBlog.users = usersReducer(targetBlog.users, action)
        }
      }
    )
  }
})

export const blogsReducer = blogsSlice.reducer

3. 调整使用方式

  • 调用子切片action时,payload需要新增blogId字段指定操作的博客:
// 给blog1新增帖子,原有post字段不变,仅新增blogId参数
dispatch(addPost({
  blogId: 'blog1',
  id: 'post1',
  author: 'user1',
  body: '测试内容',
  comments: []
}))
  • 读取状态时按路径访问即可:state.blogs.byId[blogId].posts

内容的提问来源于stack exchange,提问作者AlonF

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 16:30:04