React Router+Redux中新增任务同步至所有项目的问题修复问询
问题:Redux中新增任务被添加到所有项目的状态中
在Redux状态中新增任务时,该任务会被添加到所有项目的状态中。需要修复此问题,确保每个项目拥有独立的任务状态。相关代码如下:
App.ts
const router = createBrowserRouter([ { path: '/', element: <App/>, }, { path: 'project/:projectId', element: <ProjectItems/> } ]) const root = ReactDOM.createRoot( document.getElementById('root') as HTMLElement ); root.render( <Provider store={store}> <RouterProvider router={router}/> </Provider> );
ProjectItems.tsx
const ProjectItems = () => { const { projectId } = useParams(); const tasks = useAppSelector(state => state.task); const dispatch = useAppDispatch(); useEffect(() => { localStorage.setItem('tasks', JSON.stringify(tasks)) }, [tasks]); const addNewTask = () => { const newTask = { id: idGenerator(), title: prompt('') } dispatch(addTask({projectId, newTask})); } return ( <div className={styles.Main}> <button onClick={addNewTask}></button> </div> ) } export default ProjectItems;
Project.tsx
(此处渲染所有项目并为其添加链接)
interface IProject { id: string, title: string | null, } const Project: FC<IProject> = ({title, id}) => { const dispatch = useAppDispatch(); const handleDeleteProject = () => { dispatch(deleteProject({id})); } return ( <div className={styles.Main}> <Link to={`project/${id}`}> <div className={styles.MainWrapper}> {title} </div> </Link> <button onClick={handleDeleteProject}>Удалить</button> </div> ) } export default Project;
taskReducer.tsx
export enum TaskActions { ADD_TASK = 'ADD_TASK' } interface ITaskItem { id: string, title: string | null, } interface ITaskList { projectId: { tasks: ITaskItem[], } } interface IPayload { type: string, payload: { projectId: string, newTask: ITaskItem, }, } const data = JSON.parse(localStorage.getItem('tasks') || '[]'); const initialState: ITaskList = { projectId: { tasks: data } } export const taskReducer = (state = initialState, action: IPayload) => { switch(action.type) { case TaskActions.ADD_TASK: { const { projectId, newTask } = action.payload; const newAddTasks = state.projectId.tasks; newAddTasks.push(newTask) return { ...state, [projectId]: { ...state.projectId, tasks: newAddTasks } } } default: return state; } }
actionTask.tsx
import { TaskActions } from "../reducers/taskReducer" export const addTask = (payload: any) => { return { type: TaskActions.ADD_TASK, payload, } }
修复方案
核心问题点
- 状态结构设计错误:原
ITaskList接口使用固定的projectId属性,导致所有项目共享同一任务列表,应改为索引签名实现项目独立存储。 - 直接修改状态引用:原代码直接对
state.projectId.tasks执行push操作,违反Redux不可变更新原则,导致状态污染。 - localStorage初始化不匹配:原代码将存储数据解析为数组,与新的对象结构不兼容。
- 组件中任务获取逻辑错误:
ProjectItems中获取的是整个task状态,而非当前项目的任务列表。
修改后的代码
taskReducer.tsx
export enum TaskActions { ADD_TASK = 'ADD_TASK' } interface ITaskItem { id: string, title: string | null, } // 修改为索引签名,每个项目ID对应独立的任务列表 interface ITaskList { [projectId: string]: { tasks: ITaskItem[], } } interface IPayload { type: string, payload: { projectId: string, newTask: ITaskItem, }, } // 初始化解析为对象,而非数组 const data = JSON.parse(localStorage.getItem('tasks') || '{}'); const initialState: ITaskList = data; export const taskReducer = (state = initialState, action: IPayload) => { switch(action.type) { case TaskActions.ADD_TASK: { const { projectId, newTask } = action.payload; // 获取当前项目已有任务,无则为空数组 const currentTasks = state[projectId]?.tasks || []; // 创建新数组添加任务,保持不可变性 const updatedTasks = [...currentTasks, newTask]; return { ...state, [projectId]: { tasks: updatedTasks } } } default: return state; } }
ProjectItems.tsx
修改任务获取逻辑,只获取当前项目的任务:
// 替换原tasks获取行 const tasks = useAppSelector(state => state.task[projectId]?.tasks || []);
actionTask.tsx
明确payload类型,避免any:
import { TaskActions, ITaskItem } from "../reducers/taskReducer" export const addTask = (payload: {projectId: string, newTask: ITaskItem}) => { return { type: TaskActions.ADD_TASK, payload, } }
内容的提问来源于stack exchange,提问作者Gumblll
相关产品推荐
相关产品推荐

