React待办应用动态生成li时state更新后DOM未重渲染
问题根源
页面不重渲染的核心问题是违反了React状态更新的基本规则:直接修改state原值,没有通过setState方法触发更新。
React类组件的重渲染触发前提是调用setState方法更新状态,且更新引用类型值(数组、对象)时需要传入新的引用。你当前的onSubmit方法里直接对this.state.todoList调用push修改原数组,React检测不到状态变化,自然不会触发render执行。
除此之外你的代码还有三个逻辑问题:
- 在
handleChange的setState回调里调用onSubmit,同时输入框的onKeyDown事件也绑定了onSubmit,会导致逻辑重复触发 - 提交待办后没有清空输入框的状态值,交互体验有问题
- 用数组长度+1生成id存在重复风险,后续做删除功能时会出现key重复的报错
修复方案
- 拆分事件职责:
handleChange只负责同步输入框的实时输入值,不要在里面调用提交逻辑 - 所有状态修改统一走
setState,更新数组时用展开运算符生成新数组,不要直接修改原数组 - 提交成功后清空输入框对应的state值,替换id生成逻辑避免重复
修正后的核心代码
App组件修改后的完整逻辑:
constructor(props){ super(props) this.state = { todoItemCurrent: '', todoList: [] } this.handleChange = this.handleChange.bind(this) this.onSubmit = this.onSubmit.bind(this) } handleChange(e){ this.setState({ todoItemCurrent: e.target.value }) } onSubmit(e){ if(e.key === 'Enter'){ const newItem = this.state.todoItemCurrent.trim() // 空内容不提交 if(!newItem) return this.setState({ // 生成新数组传入,不要修改原state里的todoList todoList: [ ...this.state.todoList, { id: Date.now(), todoItem: newItem } ], // 提交后清空输入框 todoItemCurrent: '' }) } } render(){ return ( <div className="container"> <header> <h1> TO-DO LIST APP</h1> </header> <TextBoxComponent value={this.state.todoItemCurrent} placeholder="type here and hit enter to add an item" handleChange={this.handleChange} onEnter={this.onSubmit} /> <ListComponentContainer todoList={this.state.todoList} /> </div> ); } export default App;
你写的TextBoxComponent和ListComponentContainer逻辑本身没有问题,不需要修改,App组件修复后,state更新会自动触发子组件重渲染,新的li元素会正常追加到ul列表中。
补充说明:React对state的对比是浅比较,如果你直接修改原数组/对象的内容,引用地址没有变化,React会判定状态没有更新,不会触发重渲染。所有引用类型的state更新,都要返回新的引用地址(数组用展开运算符、map/filter等返回新数组的方法,对象用展开运算符或者Object.assign)。
内容的提问来源于stack exchange,提问作者Abdulrasheed Agunbiade
相关产品推荐
相关产品推荐

