在React的Movie类中添加电影到数组时出现受控输入警告问题
解决React输入控件从非受控转受控的警告问题
咱们先拆解一下你遇到的问题,这个警告的核心原因是你的输入框一开始是非受控状态,后来变成了受控状态,React不允许组件生命周期内切换这两种状态。具体到你的代码里,有两个关键问题需要修正:
1. 构造函数中重复赋值state导致初始状态丢失
你在构造函数里连续两次给this.state赋值:
this.state = {value: ''}; this.state = {list: []};//this line shows a warning
第二次赋值会完全覆盖第一次的内容,所以组件初始化时this.state.value是不存在的,这时候输入框的value={this.state.value}相当于value={undefined},React会把它当成非受控组件。当你输入内容触发handleChange后,setState设置了value,输入框就变成了受控组件,这就触发了警告。
修复方法:把state的初始化合并成一次赋值:
constructor(props) { super(props); // 合并初始状态,不要分开赋值 this.state = { value: '', list: [] }; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); this.addMovie = this.addMovie.bind(this); }
2. addMovie函数的逻辑错误
你在handleSubmit里调用this.addMovie()时没有传递参数,但addMovie函数期望接收一个value参数,这会导致新添加的电影是undefined。而且其实addMovie完全可以直接使用this.state.value,不需要额外传参。
修复方法:修改addMovie和handleSubmit的逻辑:
handleSubmit(event) { alert('A movie was submitted: ' + this.state.value); event.preventDefault(); // 不需要传参,直接调用addMovie this.addMovie(); } addMovie(){ // 直接使用state里的value,提交后清空输入框 this.setState({ list: [...this.state.list, this.state.value], value: '' }); }
完整修复后的代码
class Movie extends React.Component { constructor(props) { super(props); this.state = { value: '', list: [] }; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); this.addMovie = this.addMovie.bind(this); } handleChange(event) { this.setState({value: event.target.value}); } handleSubmit(event) { alert('A movie was submitted: ' + this.state.value); event.preventDefault(); this.addMovie(); } addMovie(){ this.setState({ list: [...this.state.list, this.state.value], value: '' }); } render() { return ( <form onSubmit={this.handleSubmit}> <label> Movie name: <input type="text" value={this.state.value} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> {/* 新增:展示已添加的电影列表 */} <ul style={{marginTop: '16px'}}> {this.state.list.map((movie, index) => ( <li key={index}>{movie}</li> ))} </ul> </form> ); } } ReactDOM.render( <Movie />, document.getElementById('root') );
这样修改后,输入框从一开始就是受控组件(初始state.value是空字符串,不是undefined),同时修复了添加电影的逻辑,还能直观看到已添加的电影列表。
内容的提问来源于stack exchange,提问作者boludo kid
相关产品推荐
相关产品推荐

