React函数式组件中如何修改对象类型状态的多个属性?
解决函数式组件中useState更新对象时丢失原有属性的问题
嗨,这个问题我太熟了!你遇到的核心问题是:每次调用setInput时,你直接用新的单属性对象替换了整个状态对象,而函数式组件的useState并不会像类组件的setState那样自动合并对象属性——所以每次更新都会丢掉之前的属性。
快速修复:使用展开运算符保留原有状态
你只需要在更新状态时,先用**展开运算符(...)**把原状态对象的所有属性复制过来,再覆盖当前要更新的属性即可。这样就能保证原有属性不丢失,同时更新新的属性。
修改后的onChange事件处理逻辑如下:
<input onChange={ e => {setInput({ ...input, title: e.target.value }) }}/>
<input onChange={ e => {setInput({ ...input, company: e.target.value }) }}/>
更优雅的方案:复用事件处理函数
为了避免重复写类似的onChange逻辑,你可以给每个输入框加上与状态属性同名的name属性,然后写一个通用的handleChange函数:
import React, { useState } from "react"; import '../styles/style.css' const Experience = (props) => { const [toggle, setToggle] = useState(false); // 先把所有需要的属性初始化到状态对象里 const [input, setInput] = useState({ title: "", company: "", date: "", location: "", description: "" }) const togglePopup = () => { setToggle(!toggle); } // 通用的输入处理函数 const handleChange = (e) => { const { name, value } = e.target; // 推荐用函数式更新,避免闭包导致的状态不一致问题 setInput(prevInput => ({ ...prevInput, [name]: value })); } return( <ul> { JSON.stringify(input) } <button onClick={togglePopup}>Work Experience</button> {toggle && <form> <div> <label>Job Title</label> </div> <div> <input name="title" value={input.title} onChange={handleChange}/> </div> <div> <label>Company</label> </div> <div> <input name="company" value={input.company} onChange={handleChange}/> </div> <div> <label>Date Worked (MM/YYYY - MM/YYYY)</label> </div> <div> <input name="date" value={input.date} onChange={handleChange}/> </div> <div> <label>Location (e.g. Los Angeles, CA)</label> </div> <div> <input name="location" value={input.location} onChange={handleChange}/> </div> <div> <label>Description</label> </div> <div> <input name="description" value={input.description} onChange={handleChange}/> </div> <button>Save</button> <button onClick={togglePopup}>Cancel</button> </form>} </ul> ) } export default Experience
为什么推荐函数式更新?
上面的代码里用了setInput(prevInput => {...})而不是直接用...input,这是因为当新状态依赖于之前的状态时,函数式更新能确保你拿到的是最新的状态值,避免因为React的状态更新异步性导致的闭包问题。
这样修改后,你就不用创建额外的状态,完全在同一个对象状态里完成所有属性的更新,效果和类组件的setState一致啦!
内容的提问来源于stack exchange,提问作者Chen
相关产品推荐
相关产品推荐

