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

React中使用push方法添加数组元素时覆盖最后项的问题求助

React Todo列表添加项异常问题解决

问题根源

  1. 组件渲染重置变量:你在组件内部声明的let todos = ["Test", "testing"]会在每次组件渲染时重新初始化,导致修改后的数组在下次渲染时被覆盖,无法持久化存储新增的todo项。
  2. 直接修改原数组违反React不可变原则:todos.push(uploadTodo)直接修改了原数组内容,而React的state更新依赖引用变化触发重新渲染。由于传递给setTodo的还是原数组的引用,React无法检测到state变化,最终表现为视图未正确更新,看起来像是每次都替换了最后一项。

修复后的完整代码

import { useState } from 'react';
import Todo from './Todo'

function App() {
  // 直接将初始todo数组作为useState的初始值,不再单独声明变量
  const [todos, setTodos] = useState(["Test", "testing"])
  const [value, setValue] = useState("")
 
  const getInput = (event) => {
    setValue(event.target.value)
  } 

  const pushTodo = () => {
    if (!value.trim()) {
      alert("Can't add an empty todo.")
      return
    }
    // 创建新数组,避免修改原state数组
    setTodos(prevTodos => [...prevTodos, value])
    // 添加后清空输入框
    setValue("")
  }

  return (
    <>
      <h1>Todo List!</h1>
      {/* 将todos数组传递给Todo组件,确保子组件能获取数据 */}
      <Todo todos={todos}></Todo>
      <button onClick={pushTodo}>Add a todo</button>
      <button>Clear todos</button><br></br>
      <input 
        placeholder="Add a todo" 
        onChange={getInput}
        value={value}
      ></input>
    </>
  );
}

export default App;

关键修改点说明

  • 正确初始化state:将初始todo数组直接传入useState,确保state作为唯一数据源,避免渲染时重置。
  • 不可变更新state:使用函数式更新setTodos(prevTodos => [...prevTodos, value]),通过扩展运算符创建新数组,保证每次更新生成新引用,让React能正确检测变化并触发渲染。
  • 优化输入校验:用!value.trim()简化空值判断,添加return避免后续代码执行。
  • 受控输入框:给input添加value={value},让输入值与state同步,保证输入状态可控。
  • 提升用户体验:添加todo后重置输入框内容,避免重复输入。
  • 传递数据给子组件:将todos数组传递给Todo组件,确保子组件能渲染所有todo项。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 18:05:17