使用display: none隐藏表单为何无法保留输入值?
为什么用display控制显示隐藏的React表单输入值会丢失?
你的问题核心出在组件的定义位置:Form1和Form2是定义在父组件的渲染函数内部的。每次父组件因为activeStep变化触发重新渲染时,这两个组件函数都会被重新创建——对于React来说,这相当于两个完全全新的组件类型,它会卸载之前的组件实例,重新挂载新的实例,所以之前输入的值自然就丢失了,哪怕你用display控制了显示隐藏。
解决方法
1. 将组件移到父组件外部定义
把Form1和Form2从父组件内部抽离出来,让它们成为稳定的组件类型,这样React就能识别出是同一个组件实例,只是控制显示隐藏,输入框的未受控值会被保留:
// 移到父组件外部,成为独立组件 const Form1 = ({ onNext }) => ( <form> <label>Form1</label> <input size={10} /> <ButtonDefaultLink name='MoveNext' className='' click={onNext} /> </form> ); const Form2 = ({ onNext }) => ( <form> <label>Form2</label> <input size={10} /> <ButtonDefaultLink name='MoveNext' className='' click={onNext} /> </form> ); // 父组件 const ParentComponent = () => { const [activeStep, setActiveStep] = useState(0); return ( <div> <div style={{ display: activeStep === 0 ? 'block' : 'none' }}> <Form1 onNext={() => setActiveStep(prev => prev + 1)} /> </div> <div style={{ display: activeStep === 1 ? 'block' : 'none' }}> <Form2 onNext={() => setActiveStep(prev => prev + 1)} /> </div> </div> ); };
2. 使用受控组件管理输入值
这也是React表单的推荐实践:用父组件的state统一管理输入值,不管组件是否被重新创建,都能通过state恢复输入内容:
const Form1 = ({ value, onChange, onNext }) => ( <form> <label>Form1</label> <input size={10} value={value} onChange={(e) => onChange(e.target.value)} /> <ButtonDefaultLink name='MoveNext' className='' click={onNext} /> </form> ); const Form2 = ({ value, onChange, onNext }) => ( <form> <label>Form2</label> <input size={10} value={value} onChange={(e) => onChange(e.target.value)} /> <ButtonDefaultLink name='MoveNext' className='' click={onNext} /> </form> ); const ParentComponent = () => { const [activeStep, setActiveStep] = useState(0); const [form1Value, setForm1Value] = useState(''); const [form2Value, setForm2Value] = useState(''); return ( <div> <div style={{ display: activeStep === 0 ? 'block' : 'none' }}> <Form1 value={form1Value} onChange={setForm1Value} onNext={() => setActiveStep(prev => prev + 1)} /> </div> <div style={{ display: activeStep === 1 ? 'block' : 'none' }}> <Form2 value={form2Value} onChange={setForm2Value} onNext={() => setActiveStep(prev => prev + 1)} /> </div> </div> ); };
内容的提问来源于stack exchange,提问作者helloworld
相关产品推荐
相关产品推荐

