React跨组件状态管理实现:点击MovieItem组件的收藏按钮将影片标题添加至Favorites组件的state
解决React组件间传递电影信息到收藏列表的问题
要实现点击MovieItem的按钮把影片信息添加到Favorites的列表里,核心是解决兄弟组件间的通信问题。因为这两个组件没有直接的父子关系,我们可以通过状态提升到它们的共同父组件(比如App.js)来实现数据传递,这是React中最常用的组件通信方式之一。
步骤1:在共同父组件中管理收藏状态
首先,我们把收藏列表的状态从Favorites移到父组件(比如App),同时定义一个添加收藏的方法,然后把这个方法传给MovieItem,把收藏列表传给Favorites。
// App.js 示例代码 import React, { Component } from 'react'; import MovieItem from './MovieItem'; import Favorites from './Favorites'; class App extends Component { state = { favorites: [ { imdbID: 'tt0068646', title: 'The Godfather', year: 1972 } ] }; // 添加收藏的方法,接收电影信息作为参数 addToFavorites = (movie) => { // 先检查是否已经在收藏列表里,避免重复添加 const isAlreadyAdded = this.state.favorites.some(item => item.imdbID === movie.imdbID); if (!isAlreadyAdded) { this.setState(prevState => ({ favorites: [...prevState.favorites, movie] })); } }; render() { return ( <div className="app"> {/* 假设这里是你的电影列表渲染,每个MovieItem传入addToFavorites方法和电影数据 */} <MovieItem Title="你的电影标题" Year="2024" Poster="海报链接" imdbID="tt1234567" addToFavorites={this.addToFavorites} /> {/* 把收藏列表传给Favorites组件 */} <Favorites movies={this.state.favorites} /> </div> ); } } export default App;
步骤2:修改MovieItem组件,调用父组件的添加方法
把按钮的点击事件从打印Title改成调用父组件传过来的addToFavorites方法,同时把当前电影的完整信息(包括imdbID、Title、Year)传过去,注意统一属性名的大小写(比如把Title改成title,和Favorites里的字段一致)。
// 修改后的MovieItem.js import React, { Component } from 'react'; import './MovieItem.css'; class MovieItem extends Component { render() { const { Title, Year, Poster, imdbID, addToFavorites } = this.props; // 统一字段名大小写,方便后续处理 const movieData = { imdbID, title: Title, year: parseInt(Year) }; return ( <article className="movie-item"> <img className="movie-item__poster" src={Poster} alt={Title} /> <div className="movie-item__info"> <h3 className="movie-item__title">{Title} ({Year})</h3> {/* 点击按钮时调用父组件的添加方法 */} <button onClick={() => addToFavorites(movieData)} type="button" className="movie-item__add-button" > Добавить в список </button> </div> </article> ); } } export default MovieItem;
步骤3:修改Favorites组件,接收父组件传递的收藏列表
现在Favorites不需要自己维护movies的state了,直接使用父组件传过来的props.movies,同时修正map时的key错误(原来用item.id,但我们的数据里是imdbID)。
// 修改后的Favorites.js import React, { Component } from 'react'; import './Favorites.css'; class Favorites extends Component { render() { // 从props接收收藏列表 const { movies } = this.props; return ( <div className="favorites"> <input value="Новый список" className="favorites__name" /> <ul className="favorites__list"> {movies.map((item) => { // 使用imdbID作为唯一key,避免警告 return <li key={item.imdbID}>{item.title} ({item.year})</li>; })} </ul> <button type="button" className="favorites__save">Сохранить список</button> </div> ); } } export default Favorites;
额外说明
- 如果你的项目已经在使用Redux(代码里看到了
import { store } from '../..'),也可以通过Redux的全局状态来管理收藏列表:在MovieItem里dispatch一个添加收藏的action,在Favorites里通过connect订阅store的收藏数据,这种方式适合更复杂的应用场景。 - 我们添加了重复检查逻辑,避免同一部电影被多次添加到收藏列表里,你可以根据需求调整这个逻辑。
内容的提问来源于stack exchange,提问作者Niyameddin
相关产品推荐
相关产品推荐

