React类组件中不Mutate原数组删除State数组元素的实现方法
嘿,作为React新手碰到状态更新尤其是数组操作的问题太正常啦!我来帮你搞定这个删除todos元素的需求,而且保证不修改原数组~
首先,先看看你当前的todos结构:每个元素是一个只有单个键值对的对象,比如{0: "Wake up"}。这种结构虽然能工作,但操作起来有点麻烦,我先按你现有的结构给出解决方案,之后再建议更友好的结构优化。
方案1:根据键删除指定元素(比如删除键为1的元素)
我们可以用数组的filter方法,它会返回一个新数组,完全不会修改原数组,完美符合React的状态更新要求:
// 定义要删除的键 const keyToDelete = 1; // 生成不包含目标元素的新数组 const newTodos = this.state.todos.filter(todo => { // 获取当前todo对象的唯一键(因为每个对象只有一个键) const todoKey = Object.keys(todo)[0]; // 把字符串类型的键转成数字,和目标键对比 return Number(todoKey) !== keyToDelete; }); // 更新state this.setState({ todos: newTodos });
方案2:根据文本内容删除指定元素(比如删除"Have breakfast")
如果你不知道键,只知道要删除的文本内容,同样用filter:
const textToDelete = "Have breakfast"; const newTodos = this.state.todos.filter(todo => { // 获取当前todo的文本值 const todoText = Object.values(todo)[0]; return todoText !== textToDelete; }); this.setState({ todos: newTodos });
更推荐的todos结构优化
其实上面的写法有点繁琐,是因为当前的todos结构不够直观。推荐你把每个todo改成包含id和text的对象,这样后续操作会方便很多:
// 初始化state时改成这样 this.state = { todos: [ { id: 0, text: "Wake up" }, { id: 1, text: "Have breakfast" }, { id: 2, text: "Have lunch" } ] };
此时根据id删除元素就简单多了:
const idToDelete = 1; // 用filter生成新数组 const newTodos = this.state.todos.filter(todo => todo.id !== idToDelete); // 更新state this.setState({ todos: newTodos });
额外小提示:使用函数式setState更安全
如果你更新状态的时候依赖于之前的state(比如删除元素肯定依赖旧的todos数组),推荐使用函数式的setState,因为React的状态更新是异步的,这种方式能确保你拿到最新的状态:
const idToDelete = 1; this.setState(prevState => ({ todos: prevState.todos.filter(todo => todo.id !== idToDelete) }));
总结一下,核心就是永远不要直接修改state里的原数组,而是用filter(或者map、concat这些返回新数组的方法)生成新数组,再通过setState更新就好啦!
内容的提问来源于stack exchange,提问作者smexyuwu
相关产品推荐
相关产品推荐

