React/Redux开发Todo列表无法删除单项问题排查
Redux 删除列表项失效问题排查
核心问题点
- 调用
removeaction时未传入待删除项的唯一标识,导致action.payload为undefined - 新增用户时仅存储了输入的纯字符串,但删除过滤逻辑判断的是
user.id字段,字符串不存在id属性,user.id恒为undefined,和undefined类型的payload比对时所有列表项都会被过滤,最终列表被清空 - 附带小问题:
logreducer直接打印state时拿到的是Redux Toolkit的Proxy对象,无法看到真实数据;列表删除按钮写了type="submit"容易触发表单误提交;列表key用索引不满足React最优渲染要求。
修复代码
1. 修正Reducer逻辑
import { createSlice, current } from "@reduxjs/toolkit"; export const userState = createSlice({ name: "users", initialState: [], reducers: { add: (state, action) => [ ...state, // 新增用户时生成带唯一id的对象,练习场景用Date.now()足够 { id: Date.now(), name: action.payload } ], remove: (state, action) => state.filter(user => user.id !== action.payload), clear: () => [], log: (state) => console.log(current(state)) // 用current包裹Proxy对象才能打印真实值 }, });
2. 修正列表渲染与事件绑定逻辑
import React from "react"; import { useDispatch, useSelector } from "react-redux"; import { userState } from "./UsersState"; export function UsersList() { const users = useSelector((state) => state.users); const dispatch = useDispatch(); function addUser(event) { event.preventDefault(); dispatch(userState.actions.add(event.target.elements.username.value)); event.target.elements.username.value = ""; // 提交后清空输入框 } // 接收待删除的用户id作为入参 function removeUser(userId) { dispatch(userState.actions.remove(userId)); } function clearList() { dispatch(userState.actions.clear()); } return ( <div> <ul className="ul"> {users.map((user) => ( <div className="list-element" key={user.id}> <li>{user.name}</li> {/* 点击时传入当前项id,按钮type改为button避免误触表单提交 */} <button onClick={() => removeUser(user.id)} type="button"> remove </button> </div> ))} </ul> <form onSubmit={addUser}> <input name="username" type="text" /> Insert name <button type="submit">Add user</button> </form> <button onClick={clearList}>Clear list</button> </div> ); }
可选优化(Store配置)
你当前使用Redux Toolkit的场景下,不需要手动引入原生redux的createStore和第三方devtools依赖,RTK内置的configureStore默认集成了devtools支持,简化后代码如下:
import { configureStore } from "@reduxjs/toolkit"; import { userState } from "./UsersState"; export const store = configureStore({ reducer: { users: userState.reducer, } });
内容的提问来源于stack exchange,提问作者naicio
相关产品推荐
相关产品推荐

