React表单子页面调用setState无法更新状态求助
问题:多子页面表单状态更新异常,子页面无法正确保存随机列表到父组件state
我搭建了一个带多子页面的表单,子页面加载时通过useEffect处理数据,调用父组件传入的handleSetInitial函数更新表单状态。生成不重复随机下拉选项的逻辑正常,但其中一个子页面调用handleSetInitial时,明明能收到列表却无法更新state,页面始终渲染默认值,另一个子页面同逻辑却正常。
父组件代码
handleSetInitial = (input, value) => () => { switch (input) { case "set_initial_npc": this.setState({ selected_npcs: [...value] }); break; case "set_initial_loc": this.setState({ selected_locs: [...value] }); break; default: break; } } render() { if (hasLoadedJson) { switch (step) { case 1: return ( <DurationPage nextStep={this.nextStep} handleChange={this.handleChange} values={values} defaults={DEFAULTS} /> ); case 2: return ( <NpcsPage nextStep={this.nextStep} prevStep={this.prevStep} handleChange={this.handleChange} handleSetInitial={this.handleSetInitial} values={values} defaults={DEFAULTS} /> ); case 3: return ( <LocationsPage nextStep={this.nextStep} prevStep={this.prevStep} handleChange={this.handleChange} handleSetInitial={this.handleSetInitial} values={values} defaults={DEFAULTS} /> ); default: // do nothing } } }
子页面(LocationsPage)代码
useEffect(() => { Refresh(); if (values.selected_locs.length === 0) { Reroll(); } }, []); const Refresh = () => { if (values.total_locs < values.selected_locs.length) { let randomLocList = values.selected_locs; randomLocList.pop(); handleSetInitial("set_initial_loc", randomLocList)(); } else if (values.total_locs > values.selected_locs.length) { Reroll(); } } const Reroll = e => { if (e) { e.preventDefault(); } let randomLocList = []; let i = 0; while (i < values.total_locs) { let index = Math.floor(Math.random() * locList.length); let loc = locList[index]; if (containsObject(loc, randomLocList)) { continue; } else { i++; randomLocList.push(loc); } } handleSetInitial("set_initial_loc", randomLocList)(); }
解决建议
修复数组引用修改问题:子组件
Refresh函数中,let randomLocList = values.selected_locs;是直接引用父组件传入的数组,后续pop()会直接修改原数组,导致state更新时可能因为引用未变化而不触发渲染。改成浅拷贝数组再操作:let randomLocList = [...values.selected_locs]; randomLocList.pop();修正useEffect依赖项:当前useEffect依赖为空数组,只会执行一次,但若父组件state更新后,子组件的
values会形成闭包,拿到的是旧值。需要将相关依赖加入数组,确保逻辑基于最新数据执行:useEffect(() => { Refresh(); if (values.selected_locs.length === 0) { Reroll(); } }, [values.total_locs, values.selected_locs.length, handleSetInitial]);使用函数式更新确保state正确性:类组件的
setState是异步操作,连续更新可能导致状态覆盖。改用函数式更新,基于最新的prevState修改:handleSetInitial = (input, value) => () => { this.setState(prevState => { switch (input) { case "set_initial_npc": return { ...prevState, selected_npcs: [...value] }; case "set_initial_loc": return { ...prevState, selected_locs: [...value] }; default: return prevState; } }); }验证props传递的正确性:检查父组件的
values是否正确包含selected_locs,以及传递给LocationsPage的values是否为父组件当前最新的state值,避免因props映射错误导致更新失效。
内容的提问来源于stack exchange,提问作者zack_falcon
相关产品推荐
相关产品推荐

