React点击提交按钮时如何重置自定义表单组件的state为默认值
核心遗漏要点
React的组件内部状态是私有的,外部组件默认无权直接访问或修改。你当前把TextField、NumberField的输入值都存储在各自组件的内部state中,作为父组件的App以及全局提交函数没有权限操作这些子组件的内部状态,自然无法触发重置。
解决方案1:状态提升(推荐)
将所有表单字段的状态统一放到公共父组件App中管理,通过props把字段值和状态更新方法传递给子组件,提交时直接修改App的状态即可同步到所有子组件,也更方便后续做表单校验、数据收集等逻辑。
修改后的完整代码如下:
import './App.css'; import React from 'react'; // 子组件改为受控组件,值和修改逻辑由父组件传入 const NumberField = (props) => { const increment = () => { props.onChange(props.value + 1) } const decrement = () => { props.onChange(Math.max(0, props.value - 1)) } const changeHandler = (e) => { const val = parseInt(e.target.value) || 0 props.onChange(val) } return ( <div> <label htmlFor={props.label}>{props.labelName}</label> <button onClick={decrement}>-</button> <input type="number" name={props.label} id={props.label} value={props.value} onChange={changeHandler}> </input> <button onClick={increment}>+</button> </div> ); } const TextField = (props) => { const changeHandler = (e) => { props.onChange(e.target.value) } return ( <div> <label htmlFor={props.label}>{props.labelName}</label> <input type="text" name={props.label} id={props.label} placeholder={props.placeholder} value={props.value} onChange={changeHandler} /> </div> ); } class App extends React.Component { constructor(props) { super(props); // 初始状态统一存在父组件 this.state = { ferry_name: "", seats: 0 } } handleSubmit = (e) => { e.preventDefault(); console.log("Form Submitted", this.state); // 直接重置父组件状态即可同步到所有子组件 this.setState({ ferry_name: "", seats: 0 }) } // 统一的状态更新方法 handleFieldChange = (fieldName, value) => { this.setState({ [fieldName]: value }) } render() { return ( <div className="App"> <div className="AppForm"> <TextField labelName="Ferry Name" label="ferry_name" placeholder="Enter the ferry name" value={this.state.ferry_name} onChange={(val) => this.handleFieldChange('ferry_name', val)} /> <div> <NumberField labelName="Number of seats" label="seats" value={this.state.seats} onChange={(val) => this.handleFieldChange('seats', val)} /> </div> <div className="formSubmit"> <button onClick={this.handleSubmit}>Book Ferry</button> </div> </div> </div> ); } } export default App;
解决方案2:使用ref调用子组件重置方法(适配现有代码改动最小)
如果不想调整现有状态结构,可以给子组件绑定ref,同时在子组件内部暴露reset方法,提交时通过ref调用所有子组件的reset方法即可。
核心改动点示例:
- 给子组件添加reset方法
class NumberField extends React.Component { // 原有逻辑不变 reset = () => { this.setState({value: 0}) } } class TextField extends React.Component { // 原有逻辑不变 reset = () => { this.setState({value: ""}) } }
- 在App中创建ref绑定到子组件,提交时调用reset
class App extends React.Component { constructor(props) { super(props); this.ferryNameRef = React.createRef() this.seatsRef = React.createRef() } handleSubmit = (e) => { e.preventDefault(); console.log("Form Submitted"); // 调用所有子组件的reset方法 this.ferryNameRef.current.reset() this.seatsRef.current.reset() } render() { return ( <div className="App"> <div className="AppForm"> <TextField ref={this.ferryNameRef} labelName="Ferry Name" label="ferry_name" placeholder="Enter the ferry name" /> <div> <NumberField ref={this.seatsRef} labelName="Number of seats" label="seats" /> </div> <div className="formSubmit"> <button onClick={this.handleSubmit}>Book Ferry</button> </div> </div> </div> ) } }
其他现有代码问题修正
- React中label的
for属性要写为htmlFor,否则无法和输入框关联 - NumberField中
increment、decrement方法未定义,点击会报错 - NumberField的changeHandler逻辑错误,当前修改的是不存在的
item字段,而非存储值的value,输入不会同步显示 - TextField的输入框未绑定
value和onChange,输入内容不会同步到组件state
内容的提问来源于stack exchange,提问作者Cameron Kilgore
相关产品推荐
相关产品推荐

