React中<ul>电影列表不显示+受控输入警告及仅展示收藏电影需求
解决你的React电影列表问题(受控输入警告+列表不显示+收藏过滤)
咱们一步一步来拆解并解决你遇到的问题:
1. 先搞定「受控/非受控输入」的警告
这个警告的根源很明确:你的文本输入框和收藏复选框绑定的movieName、favorite,在组件初始的state里根本没定义!一开始React认为这些输入是非受控的,等你输入内容触发setState后,这两个变量突然被赋值,组件就切换成了受控模式,所以触发了警告。
修正方法:在组件的constructor里初始化这两个状态:
constructor(props) { super(props); this.state = { movieName: '', // 初始化电影名称输入框的受控值 favorite: false, // 初始化收藏复选框的受控状态 list: [], showList: false // 新增状态:控制列表是否显示 }; // 方法绑定保持不变 this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); this.addMovie = this.addMovie.bind(this); }
2. 让电影列表显示出来,并且只展示收藏的电影
现在你的代码有两个核心问题导致列表看不到:
addMovie方法存的是没用的value变量,根本没把输入的电影名称和收藏状态存入列表- 点击按钮调用
listMovies只是返回了JSX,但没有把它渲染到页面上
修正addMovie方法:存储电影的完整信息
我们需要把电影名称和是否收藏作为一个对象存入列表,这样后续才能过滤出收藏的电影:
addMovie() { // 用prevState确保拿到最新的状态(因为setState是异步操作) this.setState(prevState => ({ list: [...prevState.list, { name: prevState.movieName, isFavorite: prevState.favorite }], movieName: '', // 提交后清空输入框 favorite: false // 提交后重置复选框 })); }
让列表能被渲染到页面上
删掉原来的listMovies方法,改成用showList状态控制列表的显示/隐藏:
在render方法里,把按钮和列表部分改成这样:
<button onClick={() => this.setState(prevState => ({ showList: !prevState.showList }))}> {this.state.showList ? 'Hide Movies' : 'List Movies'} </button> {/* 当showList为true时,渲染只包含收藏电影的列表 */} {this.state.showList && ( <ul> {this.state.list .filter(movie => movie.isFavorite) // 过滤出标记为收藏的电影 .map((movie, index) => ( <li key={index}>{movie.name}</li> ))} </ul> )}
完整的修正后代码
class Movie extends React.Component { constructor(props) { super(props); this.state = { movieName: '', favorite: false, list: [], showList: false }; this.handleChange = this.handleChange.bind(this); this.handleSubmit = this.handleSubmit.bind(this); this.addMovie = this.addMovie.bind(this); } handleChange(event) { const target = event.target; const value = target.type === 'checkbox' ? target.checked : target.value; const name = target.name; this.setState({ [name]: value }); } handleSubmit(event) { event.preventDefault(); this.addMovie(); } addMovie() { this.setState(prevState => ({ list: [...prevState.list, { name: prevState.movieName, isFavorite: prevState.favorite }], movieName: '', favorite: false })); } render() { return ( <div> <form onSubmit={this.handleSubmit}> <label> Movie name: <input name="movieName" type="text" value={this.state.movieName} onChange={this.handleChange} /> Favorite? <input name="favorite" type="checkbox" checked={this.state.favorite} onChange={this.handleChange} /> </label> <input type="submit" value="Submit" /> </form> <button onClick={() => this.setState(prevState => ({ showList: !prevState.showList }))}> {this.state.showList ? 'Hide Movies' : 'List Movies'} </button> {this.state.showList && ( <ul> {this.state.list .filter(movie => movie.isFavorite) .map((movie, index) => ( <li key={index}>{movie.name}</li> ))} </ul> )} </div> ); } } ReactDOM.render( <Movie />, document.getElementById('root') );
现在你再运行代码:
- 不会再有受控/非受控输入的警告
- 提交电影后,点击「List Movies」按钮就能看到所有标记为收藏的电影
- 再次点击按钮可以隐藏列表
内容的提问来源于stack exchange,提问作者boludo kid
相关产品推荐
相关产品推荐

