React中如何根据子组件操作在父组件条件渲染指定按钮
修复方案
核心问题
你现有代码的核心问题有3个:
- 父组件中
selectedList是普通变量,不属于React的响应式状态,修改后不会触发组件重渲染,所以按钮的显示状态不会更新 - 子组件直接修改父组件传入的数组,违反React单向数据流的设计规范,容易出现状态不同步的问题
- 没有给「Let's go」按钮添加条件渲染的判断逻辑
修复后代码
父组件代码
import { useState } from 'react'; export default function Index(data) { const info = data.data.body.result; // 用useState定义响应式的选中列表 const [selectedList, setSelectedList] = useState([]); // 子组件点击后触发的选中/取消选中逻辑 const handleSelect = (movieId) => { setSelectedList(prev => { if (prev.includes(movieId)) { // 已选中就移除 return prev.filter(id => id !== movieId); } else { // 未选中就添加 return [...prev, movieId]; } }) } return ( <> <main className={parentstyle.main_container}> <NavBar /> <div className={style.searchbar_container}> <SearchBar /> </div> <div className={style.card_container}> {info.map((movie, i) => { return ( <MovieCard movieName={movie.name} key={movie._id} // 不要用index当key,用唯一的movie id更稳妥 movieId={movie._id} isSelected={selectedList.includes(movie._id)} onSelect={handleSelect} /> ); })} </div> </main> {/* 条件渲染:选中列表不为空时才显示按钮 */} {selectedList.length > 0 && <button className={style.done}>Let's go!</button>} </> ); }
MovieCard子组件代码
export default function MovieCard({ movieName, movieId, isSelected, onSelect }) { return ( <div> <img className={isSelected ? style.movie_selected : style.movie} src={`images/movies/${movieName}.jpg`} alt={movieName} onClick={() => onSelect(movieId)} /> <h3 className={style.title}>{movieName}</h3> </div> ); }
主要改动说明
- 父组件用
useState管理选中列表,每次修改状态都会自动触发重渲染,自动更新按钮显示状态和子组件的选中样式 - 子组件不需要自己维护选中状态,直接使用父组件传入的
isSelected参数判断样式,避免父子状态不同步 - 子组件点击后通过回调函数通知父组件更新状态,符合React单向数据流规范
- 修正了map循环的key值,用唯一的影片ID代替索引,避免列表渲染出现异常
内容的提问来源于stack exchange,提问作者moemous
相关产品推荐
相关产品推荐

