
在 React 函数组件中,若将数组(如 itemList)声明为普通变量而非状态,它会在每次组件重渲染时被重新初始化为空数组,导致新增元素无法累积。正确做法是使用 useState 管理该数组,并通过函数式更新确保基于最新状态追加数据。
在 React 函数组件中,若将数组(如 `itemList`)声明为普通变量而非状态,它会在每次组件重渲染时被重新初始化为空数组,导致新增元素无法累积。正确做法是使用 `useState` 管理该数组,并通过函数式更新确保基于最新状态追加数据。
问题根源在于:const itemList = [] 是一个局部变量,位于函数组件 App() 的顶层作用域内。每当 useState 触发状态更新(如 updateItm 被调用),React 会重新执行整个 App 函数,从而每次都重新声明并初始化 itemList = [] —— 这就是为什么你看到的始终是单元素数组,旧值被“覆盖”而非“追加”。
✅ 正确解法:将 itemList 改为受控的 React 状态,并在 addItem 中使用函数式更新(setItemList(prev => [...prev, newItem])),确保操作基于当前最新状态:
import { useState } from 'react';
function App() {
const [item, updateItem] = useState(''); // 初始化为空字符串更安全
const [itemList, setItemList] = useState([]); // ✅ 使用 useState 管理数组
const listenInput = (e) => {
updateItem(e.target.value);
};
const addItem = () => {
if (!item.trim()) return; // 防止添加空字符串
setItemList(prev => [...prev, item]); // ✅ 函数式更新:基于上一状态追加
updateItem(''); // 可选:清空输入框
};
return (
<div classname="main-div">
<div classname="center-div">
<h1>To Do</h1>
<input value="{item}" onchange="{listenInput}" type="text" name="item" placeholder="Add item"><button onclick="{addItem}">+</button>
<ol>
{itemList.map((it, idx) => (
<li key="{idx}">{it}</li>
))}
</ol>
</div>
</div>
>
);
}
export default App;
? 关键要点总结:
- ❌ 普通变量(const arr = [])无法跨渲染周期保留数据;
- ✅ 所有需要持久化的数据必须通过 useState、useRef(仅适用于不触发重渲染的引用)等 React Hook 管理;
- ✅ 使用函数式更新 setState(prev => [...prev, newValue]) 是处理数组/对象状态变更的最佳实践,避免闭包导致的状态陈旧问题;
- ✅ 建议为受控输入框显式绑定 value={item},并同步更新 onChange,保证输入一致性;
- ⚠️ 注意:key 在列表渲染中不可使用索引(idx)当存在动态增删时,此处仅为简化示例;生产环境应使用唯一 ID。
通过以上修正,输入 “mango” → 点击 “+” → 再输入 “apple” → 再点击 “+”,itemList 将正确变为 ['mango', 'apple'],实现真正的累加效果。











