React父组件重渲染时子组件更新的number值丢失问题咨询
问题原因
- 核心问题1:父组件的条件渲染逻辑错误。初始
number=0时没有返回合法的渲染结果,且原有逻辑只要number<=0就会直接卸载FirstChild组件,React会在组件卸载时销毁组件内部的所有本地状态,下次组件重新挂载时useState会重新读取初始值,之前输入的内容自然会丢失。 - 核心问题2:
FirstChild内部的本地状态qtd和父组件传入的props.number没有做同步绑定。useState(props.number)只会在组件首次挂载时读取一次props值作为初始状态,后续父组件重渲染传入新的props时,本地qtd不会自动更新,很容易出现状态不一致。 - 附加问题:输入框是受控组件但没有绑定
value属性,本身就存在输入值和状态不同步的隐患。
修复方案
根据你是否需要保留「输入完成后点击按钮才同步值给父组件」的交互,选对应方案即可:
方案1:保留点击提交才同步的交互
- 修改父组件渲染逻辑:不要根据
number值卸载FirstChild,仅控制SecondChild的条件渲染,避免输入组件被卸载导致状态销毁。 - 给
FirstChild增加props变化同步逻辑,补全输入框的value绑定。
修正后的父组件代码
const [number, setNumber] = useState(0); // 移除原来的if条件分支判断,始终返回合法UI return ( <div id='main'> <div> {/* FirstChild始终保持挂载,不被条件卸载 */} <Firstchild setNumber={setNumber} number={number}/> {/* 仅控制SecondChild在number>0时渲染 */} {number > 0 && <SecondChild number={number}/>} </div> </div> );
修正后的FirstChild代码
import { useState, useEffect } from 'react'; const [qtd, setQtd] = useState(props.number); // 监听父组件传入的number变化,同步更新本地状态 useEffect(() => { setQtd(props.number); }, [props.number]); function updateNumber(){ // 转成数字类型再传给父组件,避免状态变成字符串 props.setNumber(Number(qtd)); } const handleChange = event => { setQtd(event.target.value); }; return( <> {/* 补全value绑定,让输入框和本地状态实时同步 */} <input type="number" name="integerTimes" className="integerTimes" placeholder='Insira aqui' id="qtd" onChange={handleChange} value={qtd} /> <button id="submitTimes" onClick={updateNumber}>Enviar</button> </> );
方案2:不需要点击提交,实时同步值(推荐)
直接把输入状态上移到父组件维护,FirstChild不存本地状态,从根源上避免父子状态不同步、子组件卸载丢状态的问题。
修正后的FirstChild代码
function Firstchild({number, setNumber}) { const handleChange = event => { // 输入时直接同步修改父组件的状态,统一转数字类型 setNumber(Number(event.target.value)); }; return( <> <input type="number" name="integerTimes" className="integerTimes" placeholder='Insira aqui' id="qtd" onChange={handleChange} value={number} /> <button id="submitTimes">Enviar</button> </> ); }
父组件代码和方案1的父组件代码一致即可,状态统一存在父组件,无论怎么重渲染都不会出现值丢失的问题。
注意事项
- 不要在函数组件的顶层条件分支里写return渲染逻辑,很容易出现某个分支无返回值、或者意外卸载组件的问题,条件渲染尽量用三元表达式或者
&&运算符写在JSX内部。 - 受控表单组件必须绑定
value属性对应状态,否则会出现输入显示和状态值不一致的异常。
内容的提问来源于stack exchange,提问作者c4xp
相关产品推荐
相关产品推荐

