如何判断React中text表单字段是否被修改?修改时prop同步变化如何解决
问题根因
你当前的组件是受控组件,输入框的value直接绑定了父组件传入的field_value属性,在handleChange触发的第一时间就调用了this.props.test(id, event.target.value)通知父组件更新状态,父组件更新后会把最新的值重新通过field_value传给当前组件,你后续对比event.target.value和this.props.field_value的时候,父组件大概率已经完成了状态更新,field_value已经变成了最新的输入值,自然无法和初始值做对比。
你之前把prop存入state没生效,大概率是没有区分「初始prop值」和「动态更新的prop值」,如果每次prop更新都同步覆盖state里存的值,自然也无法保留初始值做对比。
解决方法
提供两种可直接落地的方案:
方案1:组件内部存储初始值
在组件初始化时将初始的field_value存入state,这个值全程不跟随prop更新,只用来做变更对比:
class YourComponent extends React.Component { constructor(props) { super(props); this.state = { valid: true, changed: false, // 只在初始化时存一次初始值,后续不再主动更新 initialFieldValue: props.field_value }; } handleChange = (id, event) => { const newValue = event.target.value; // 先做校验和变更判断,再通知父组件更新 const isValid = this.validate(newValue) || (newValue === "" && !this.props.required); // 和存在state里的初始值对比,不是和当前prop比 const isChanged = newValue !== this.state.initialFieldValue; this.setState({ valid: isValid, changed: isChanged }); this.props.canSubmit(isValid); this.props.test(id, newValue); } render() { return ( <div className="mb-3" > <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" /> <span> <TextField id="outlined-basic" variant="standard" type="text" aria-describedby="emailHelp" value={this.props.field_value || ""} onChange={event => this.handleChange(this.props.field_id, event)} label={this.props.field_label} error={!this.state.valid} /> <Icon onClick={this.handleDescription} className="description">help_outlined</Icon> {this.state.changed ? <Icon>edit</Icon> : null} </span> </div> ) } }
如果你的初始field_value是父组件异步获取后传入的,不是组件初始化时就有有效值,可以补充componentDidUpdate逻辑处理初始值存储:
componentDidUpdate(prevProps) { // 只在第一次拿到有效值的时候存初始值,后续不再更新 if (prevProps.field_value === undefined && this.props.field_value !== undefined) { this.setState({ initialFieldValue: this.props.field_value }) } }
方案2:父层传入初始值
直接让父组件额外传一个initial_field_value属性,存储字段的初始默认值,你直接拿这个属性做变更对比即可,不需要自己维护初始值:
// 判断变更的时候直接用父层传入的初始值对比 if (event.target.value !== this.props.initial_field_value) { this.setState({ changed: true }) } else { this.setState({ changed: false }) }
内容的提问来源于stack exchange,提问作者Matheus Goulart
相关产品推荐
相关产品推荐

