React分页切换时input组件value属性不更新问题原因及解决方法
问题原因
useState的初始赋值仅在组件首次挂载时执行1次,切换分页时如果React复用了现有ContentRowTipJar组件实例(未触发卸载重渲染),组件内部的tipJarPrice状态不会自动同步新传入的props.low/med/high值,输入框绑定的是内部状态因此不会更新。- 额外存在代码错误:第二档价格输入框的
name属性写为mid,但状态对象的对应key是med,输入修改时会把值存在tipJarPrice.mid字段中,无法正确同步到绑定的tipJarPrice.med上。
解决方法
方案1:添加唯一key(改动最小)
在父组件渲染ContentRowTipJar时,给组件添加唯一的key属性,取值可以用当前行的唯一id、或者「分页标识+行id」的组合,示例:
// 父组件渲染逻辑 {list.map(item => <ContentRowTipJar key={item.id} id={item.id} low={item.low} med={item.med} high={item.high} ... />)}
key变更时React会直接销毁旧组件实例、挂载新实例,内部状态会自动用新props重新初始化。
方案2:监听props变化同步内部状态
在组件内添加useEffect监听props的价格参数变化,触发时更新内部状态并重置修改标记:
useEffect(() => { setTipJarPrice({ low: props.low, med: props.med, high: props.high }) setIsChanged(false) // 也可以直接监听props.id,确保行切换时强制更新 }, [props.low, props.med, props.high])
方案3:改为完全受控组件(推荐,避免状态不同步)
移除组件内部的tipJarPrice和isChanged状态,直接绑定父组件传入的props值,修改时直接调用父组件的更新方法,完全由父组件管控状态:
// 修改后组件简化逻辑 const ContentRowTipJar = (props) => { const handleChange = (e) => { const newPrice = { low: props.low, med: props.med, high: props.high, [e.target.name]: parseFloat(e.target.value), } props.onTipJarChange(newPrice) }; let classes = `${props.className} ${styles["tipjar"]}`; return ( <> <td className={classes}> <input id={`low_${props.id}`} type="number" name="low" min="0" step="0.01" onChange={handleChange} value={props.low} className={styles["contentrowprice-input"]} /> </td> {/* 其余输入框同理绑定props对应值,同时修正name为med */} <td className={classes}> <input id={`med_${props.id}`} type="number" name="med" min="0" step="0.01" onChange={handleChange} value={props.med} className={styles["contentrowprice-input"]} /> </td> <td className={classes}> <input id={`high_${props.id}`} type="number" name="high" min="0" step="0.01" onChange={handleChange} value={props.high} className={styles["contentrowprice-input"]} /> </td> </> ); };
修复代码错误
把第二档输入框的name="mid"修正为name="med",和状态key保持一致,避免修改不生效的问题。
内容的提问来源于stack exchange,提问作者anubhav
相关产品推荐
相关产品推荐

