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

React JS中为何无法删除数组的第一个元素?

问题描述

我有一系列复选框,勾选复选框时会将对应复选框的id添加到数组中,取消勾选时则会将对应id从数组中移除,其余逻辑均运行正常,但存在一个异常现象:我第一个点击的复选框(会成为数组的首项)永远无法被移除,也就是数组的第一个元素始终无法删除。

以下是复选框发生状态变更时触发的处理函数代码:

const [genres, setGenres] = useState([])

const checkChange = event => {
  const targetId = event.target.id
  const indexOfTargetId = genres.indexOf(targetId)

  if (indexOfTargetId === -1)
    setGenres([...genres, targetId])
  else genres.splice(indexOfTargetId, indexOfTargetId) 
}
问题原因

代码存在两个核心错误:

  • Array.splice()方法的第二个参数是需要删除的元素个数,不是删除操作的截止索引。当前代码传入的是目标id对应的索引值:当要删除的是数组首项时,索引值为0,相当于传入删除数量0,不会删除任何元素;当目标元素索引大于0时,传入的索引值为1、2这类正整数,碰巧符合删除1个元素的要求,才会表现为其余逻辑正常。
  • else分支直接调用splice修改原state数组,既没有调用setGenres触发视图更新,还违反了React state不可变的原则,本身就是不规范的写法。
修复方案

方案1:修正原有splice逻辑

先浅拷贝原数组避免直接修改state,同时修正splice的参数,最后通过setGenres更新状态:

const [genres, setGenres] = useState([])

const checkChange = event => {
  const targetId = event.target.id
  const indexOfTargetId = genres.indexOf(targetId)

  if (indexOfTargetId === -1) {
    setGenres([...genres, targetId])
  } else {
    const newGenres = [...genres]
    // 第二个参数固定传1,代表仅删除当前索引位置的1个元素
    newGenres.splice(indexOfTargetId, 1)
    setGenres(newGenres)
  }
}

方案2:更简洁稳妥的写法

用filter方法直接生成过滤后的新数组,同时配合setState的函数式更新,避免闭包拿到旧state值的隐患:

const [genres, setGenres] = useState([])

const checkChange = event => {
  const targetId = event.target.id
  setGenres(prevGenres => 
    prevGenres.includes(targetId)
      ? prevGenres.filter(id => id !== targetId)
      : [...prevGenres, targetId]
  )
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 12:06:19