如何在React中使用useState创建并持久化数组的自增ID
你的问题出在两个地方:一是每次调用addTask时都把nextId固定设为1,没有基于现有列表的ID计算下一个值;二是直接通过document.getElementById获取输入值不符合React的状态管理思路,应该用useState来管理输入内容。
下面是具体的修复方案:
1. 用State管理输入框内容
添加一个状态变量存储输入框的值,替代直接操作DOM的方式,符合React单向数据流的设计:
const [inputText, setInputText] = useState('');
然后修改输入框标签,绑定值和变更事件:
<input type='text' id="input-textbox" value={inputText} onChange={(e) => setInputText(e.target.value)} />
2. 正确计算自增ID
每次新增任务时,从当前列表中提取最大ID并加1,作为新任务的ID。同时推荐使用函数式更新列表状态,确保依赖旧状态时能拿到最新值:
function addTask() { if (!inputText.trim()) return; // 避免添加空白任务 setList(prevList => { // 计算当前列表的最大ID const maxId = prevList.length > 0 ? Math.max(...prevList.map(item => item.id)) : 0; return [ ...prevList, { id: maxId + 1, title: inputText.trim() } ]; }); setInputText(''); // 添加后清空输入框 }
修改后的完整代码
import { useState } from 'react'; function TodoList() { const initialList = [ { id: 0, title: 'Buy milk' }, ]; const [list, setList] = useState(initialList); const [inputText, setInputText] = useState(''); function addTask() { if (!inputText.trim()) return; setList(prevList => { const maxId = prevList.length > 0 ? Math.max(...prevList.map(item => item.id)) : 0; return [ ...prevList, { id: maxId + 1, title: inputText.trim() } ]; }); setInputText(''); } return ( <> <label htmlFor="item">Type item here: </label> <input type='text' id="input-textbox" value={inputText} onChange={(e) => setInputText(e.target.value)} /> <div> <button onClick={addTask}>Add task</button> {list.map(item => ( <div key={item.id}> {/* 必须添加唯一key,优化React渲染效率 */} {item.id} : {item.title} </div> ))} </div> </> ) } export default TodoList;
额外提示
- 列表渲染时必须给每个项添加唯一的
key属性,这里用item.id是最合适的选择。 - 函数式更新
setList(prevList => ...)能避免因React状态异步更新导致的ID计算错误,连续点击添加按钮也能保证ID正确自增。
内容的提问来源于stack exchange,提问作者biancang
相关产品推荐
相关产品推荐

