React使用现有对象初始化useState失败问题求助
问题:React模态框表单初始化值异常
我是React新手,想在模态框中收集表单数据并发送请求,同时让输入框从传入的props.itemInfo获取默认值。尝试用props.itemInfo的属性初始化formData状态,但控制台显示itemInfo.itemID为3,formData.itemID却为undefined,传入的对象数据正常,求问题原因及可行实现方案。
相关代码
function Parent() { const [state, setState] = useState(false); const [itemInfo, setItemInfo] = useState({}) // itemInfo get from somewhere in the middle return ( <div> <button onClick={() => setState(true)}> Render modal </button> <Modal itemInfo={itemInfo} state={state} setState={setState} /> </div> ) }; function Modal(props) { let itemInfo = props.itemInfo; console.log(typeof itemInfo); // 1 console.log(itemInfo); // 2 /* I also tried const [formData, setFormData] = useState({itemInfo}); but not working */ const [formData, setFormData] = useState({ itemID: itemInfo.itemID, userID: itemInfo.userID, isActive: itemInfo.isActive, purchaseCost: itemInfo.purchaseCost, dateModified: itemInfo.dateModified, dateCreated: itemInfo.dateCreated, description: itemInfo.description, itemGrouping: itemInfo.itemGrouping, }); console.log(itemInfo.itemID); // 3 console.log(formData.itemID); // 4 const handleCloseModal = () => { props.setState(false); }; const handleFormChange = (e) => { const { id, value } = e.target; setFormData((prevState) => ({ ...prevState, [id]: value, })); }; const handleSubmit = (e) => { e.preventDefault(); // send request with formData }; return ( <ReactModal isOpen={props.state} ariaHideApp={false}> <form id="login"> <div> <label>Grouping: </label> <input id="grouping" type="text" defaultValue={formData.itemGrouping} onChange={handleFormChange} required /> </div> <div> <label>Cost: </label> <input id="cost" type="text" defaultValue={formData.purchaseCost} onChange={handleFormChange} required /> </div> <div> <label>Description: </label> <input id="description" type="text" defaultValue={formData.description} onChange={handleFormChange} required /> </div> <button type="submit" onClick={handleSubmit}> Submit </button> </form> <button onClick={handleCloseModal}>Close Modal</button> </ReactModal> ); }
传入的对象数据
{ "itemID": 3, "userID": 2, "isActive": 1, "purchaseCost": 0, "dateModified": "2022-10-05 03:44:07", "dateCreated": "2022-10-05", "description": "Gift from my sister for my 29th birthday!", "itemGrouping": null }
控制台输出
object // 1 { "itemID": 3, "userID": 2, "isActive": 1, "purchaseCost": 0, "dateModified": "2022-10-05 03:44:07", "dateCreated": "2022-10-05", "description": "Gift from my sister for my 29th birthday!", "itemGrouping": null } // 2 3 // 3 undefined // 4
问题原因
- useState初始化特性:React的
useState初始化值仅在组件首次渲染时执行一次。你的Parent组件中itemInfo初始值是空对象{},此时Modal首次渲染,formData会用空对象的属性初始化(所有值都是undefined)。后续itemInfo更新为完整数据时,useState的初始化逻辑不会再次触发,所以formData仍保持首次渲染的undefined值。 - 控制台日志时序:你看到的
itemInfo.itemID为3是组件更新后的日志,但formData的初始化已经在首次渲染完成,不会随itemInfo的更新自动同步。
可行实现方案
方案1:用useEffect监听props变化同步formData
通过useEffect监听props.itemInfo的更新,手动同步formData状态,确保每次模态框拿到新数据时,表单默认值能同步更新。
修改后的Modal组件代码:
function Modal(props) { // 先初始化空状态 const [formData, setFormData] = useState({ itemID: '', userID: '', isActive: '', purchaseCost: '', dateModified: '', dateCreated: '', description: '', itemGrouping: '', }); // 监听itemInfo变化,同步更新formData useEffect(() => { // 确保有有效数据时再更新 if (props.itemInfo?.itemID) { setFormData({ itemID: props.itemInfo.itemID, userID: props.itemInfo.userID, isActive: props.itemInfo.isActive, purchaseCost: props.itemInfo.purchaseCost, dateModified: props.itemInfo.dateModified, dateCreated: props.itemInfo.dateCreated, description: props.itemInfo.description, itemGrouping: props.itemInfo.itemGrouping, }); } }, [props.itemInfo]); // 依赖项设为itemInfo,变化时触发 const handleCloseModal = () => { props.setState(false); }; const handleFormChange = (e) => { const { id, value } = e.target; // 修正输入框id与formData的key一致,确保更新正确字段 setFormData((prevState) => ({ ...prevState, [id]: value, })); }; const handleSubmit = (e) => { e.preventDefault(); console.log('提交数据:', formData); // 此处发送请求 }; return ( <ReactModal isOpen={props.state} ariaHideApp={false}> <form id="itemForm" onSubmit={handleSubmit}> <div> <label>Grouping: </label> <input id="itemGrouping" // 修正id与formData的key匹配 type="text" value={formData.itemGrouping ?? ''} // 用value实现受控组件,处理null值 onChange={handleFormChange} required /> </div> <div> <label>Cost: </label> <input id="purchaseCost" // 修正id type="number" // 成本用number类型更合理 value={formData.purchaseCost} onChange={handleFormChange} required /> </div> <div> <label>Description: </label> <input id="description" type="text" value={formData.description} onChange={handleFormChange} required /> </div> <button type="submit">Submit</button> </form> <button onClick={handleCloseModal}>Close Modal</button> </ReactModal> ); }
额外优化点
- 将表单改为受控组件(用
value替代defaultValue),确保表单数据与formData状态完全同步。 - 修正输入框
id与formData的key一致,避免handleFormChange无法正确更新字段。 - 处理
itemGrouping为null的情况,用?? ''转为空字符串避免输入框报错。
方案2:控制Modal渲染时机
在Parent组件中,只有当itemInfo有完整数据时才渲染Modal,避免首次渲染用空对象初始化:
function Parent() { const [state, setState] = useState(false); const [itemInfo, setItemInfo] = useState({}) return ( <div> <button onClick={() => setState(true)}> Render modal </button> {/* 只有itemInfo有itemID时才渲染Modal */} {itemInfo.itemID && <Modal itemInfo={itemInfo} state={state} setState={setState} />} </div> ) };
内容的提问来源于stack exchange,提问作者StoneForest
相关产品推荐
相关产品推荐

