提取复用React通用输入组件失效,请求排查错误原因
React通用InputField组件故障排查与修复
问题背景
将原有可正常运行的输入组件提取为InputField通用组件后,组件无法按预期工作,以下是相关代码及错误分析:
原有可正常运行的组件代码
<div className="form-group col-md-6"> <label className='inp-lbl'>{utl.nameWord()}</label> <div className='inp-name'> <input type="text" ref="name" defaultValue={this.name} onChange={e => { this.setState((state) => { return {name: e.target.value}; }); }} /> </div> </div>
现有通用组件、调用方式及handleChange函数
通用组件代码
class InputField extends React.Component { constructor(props) { super(props); this.state = { labelStr: props.lbStr, nameStr: props.nmStr, defltVal: props.dfVl, onChgFnc: props.onChFn }; // this.onChgFnc = props.onChFn } render() { return ( <React.Fragment> <div className="form-group col-md-6"> <label className='inp-lbl'>{this.state.labelStr}</label> <div className='inp-name'> <input type="text" ref={this.state.nameStr} defaultValue={this.state.defltVal} onChange={this.state.onChgFnc} /> </div> </div> </React.Fragment> ) } }
调用方式
<InputField lbStr={utl.nameWord()} nmStr='name' dfVl={this.name} onChFn={handleChange} />
handleChange函数
function handleChange(event) { this.setState((state) => { return {name: event.target.value}; }) }
错误点分析
- props存入state导致数据不同步:通用组件将父组件传递的props存入自身state,当父组件更新props时,子组件state不会自动更新,导致视图和数据脱节。
- ref属性使用错误:字符串ref已被React废弃,且直接从state读取ref值的方式不符合规范,无法正确绑定引用。
- handleChange的this指向丢失:直接传递
handleChange函数时,函数内部的this会指向undefined(严格模式下),调用this.setState会抛出错误。 - 非受控组件的局限性:使用
defaultValue仅能设置初始值,当父组件的this.name更新时,输入框的值不会同步变化,应该改用受控组件模式(value+onChange)。
修正后的代码
通用组件(改为直接使用props,采用受控组件)
class InputField extends React.Component { render() { const { lbStr, nmStr, value, onChange } = this.props; return ( <div className="form-group col-md-6"> <label className='inp-lbl'>{lbStr}</label> <div className='inp-name'> <input type="text" name={nmStr} // 用name属性标识字段,替代废弃的字符串ref value={value} onChange={onChange} /> </div> </div> ) } }
调用方式(传递value和绑定好this的onChange)
// 先在父组件构造函数中绑定handleChange constructor(props) { super(props); this.handleChange = this.handleChange.bind(this); } // 调用组件时 <InputField lbStr={utl.nameWord()} nmStr='name' value={this.state.name} onChange={this.handleChange} />
修正后的handleChange函数(支持通用字段更新)
handleChange(event) { const { name, value } = event.target; this.setState({ [name]: value // 利用name属性实现通用更新,无需硬编码字段名 }); }
内容的提问来源于stack exchange,提问作者Michel
相关产品推荐
相关产品推荐

