React组件未读取默认state,报错Cannot read properties of null (reading 'language')
报错根因
你触发的空值读取错误是SearchForm组件未正确初始化自身状态导致的:你仅在SearchForm的componentDidMount生命周期中执行setState赋值,而React组件的render执行时机早于componentDidMount,首次渲染时访问this.state.language时,this.state还处于未初始化的空值状态,直接触发报错。
除此之外你的代码还存在3个逻辑问题:
- 父组件
SearchApp中定义的language状态、handleClickLang方法没有通过props传递给SearchForm子组件,两者状态完全隔离,你在父组件初始化的language值完全没有被传递到子组件使用 - 当前
SearchForm组件中没有定义handleClickLang方法,就算修复了状态初始化问题,单选框触发onChange事件时也会报方法未定义的错误 - 如果你打算将
language状态提升到父组件统一维护,不需要在子组件再单独维护一份重复状态,否则会出现父子组件状态不同步的问题
修复方案
方案1:状态保留在父组件统一维护(推荐)
这种方案符合React状态提升的最佳实践,避免多组件维护同一份状态导致的不一致问题。
- 修改父组件
SearchApp的render方法,将状态和回调方法通过props传递给子组件:
// SearchApp 组件render方法修改 render() { return ( <> <SearchForm language={this.state.language} handleClickLang={this.handleClickLang} /> </> ); }
- 简化子组件
SearchForm逻辑,直接使用父组件传递的props,不需要自己维护language状态:
class SearchForm extends React.Component { constructor(props) { super(props); this.handleSubmit = this.handleSubmit.bind(this); this.subjRef = React.createRef(); } handleSubmit(e) { e.preventDefault(); window.alert("sometext"); } render() { return ( <form onSubmit={this.handleSubmit} className="my-3"> <div className="form-row"> <div className="form-group col-md-8"> <p>Choose language</p> </div> </div> <div className="form-row"> <div className="form-check"> <label> <input type="radio" name="react-tips" value="English" checked={this.props.language === 'English'} onChange={this.props.handleClickLang} className="form-check-input" /> English </label> </div> <div className="form-check"> <label> <input type="radio" name="react-tips" value="Russian" checked={this.props.language === 'Russian'} onChange={this.props.handleClickLang} className="form-check-input" /> Russian </label> </div> </div> </form> ); } }
方案2:状态保留在子组件单独维护
如果不需要父组件感知language状态变化,可以直接在子组件内部完成状态初始化和方法定义:
class SearchForm extends React.Component { constructor(props) { super(props); this.handleSubmit = this.handleSubmit.bind(this); this.subjRef = React.createRef(); // 直接在constructor初始化state,不要等到componentDidMount this.state = { language: 'English' }; // 绑定本组件内的方法 this.handleClickLang = this.handleClickLang.bind(this); } handleSubmit(e) { e.preventDefault(); window.alert("sometext"); } // 子组件内部定义切换语言的方法 handleClickLang = changeEvent => { this.setState({ language: changeEvent.target.value }); }; render() { return ( <form onSubmit={this.handleSubmit} className="my-3"> <div className="form-row"> <div className="form-group col-md-8"> <p>Choose language</p> </div> </div> <div className="form-row"> <div className="form-check"> <label> <input type="radio" name="react-tips" value="English" checked={this.state.language === 'English'} onChange={this.handleClickLang} className="form-check-input" /> English </label> </div> <div className="form-check"> <label> <input type="radio" name="react-tips" value="Russian" checked={this.state.language === 'Russian'} onChange={this.handleClickLang} className="form-check-input" /> Russian </label> </div> </div> </form> ); } }
内容的提问来源于stack exchange,提问作者dooglex
相关产品推荐
相关产品推荐

