React Native基于AsyncStorage实现电影WatchList收藏功能
你已经在代码里引入了@react-native-async-storage/async-storage,不需要额外安装依赖,直接按以下步骤修改代码即可:
1. 补充状态定义
找到组件内的useState声明块,新增收藏状态标记:
const [loading, setLoading] = useState(true); const [details, setDetails] = useState(); const [favourites, setFavourites] = useState([]); // 新增:标记当前电影是否已加入清单 const [isFavourite, setIsFavourite] = useState(false);
顺便提一句:你原有代码里拉取视频的接口路径模板字符串写法有误,/movie/${props.route.params.movieId/videos} 要改成 /movie/${props.route.params.movieId}/videos,否则视频接口会请求失败。
2. 添加本地存储操作方法
在getGenre方法同级位置,添加以下逻辑:固定存储key、读取本地清单、切换收藏状态
// 本地存储固定key,避免读写时key不一致 const WATCHLIST_KEY = '@movie_watchlist'; // 页面加载时读取本地已存的观影清单 const loadLocalWatchlist = async () => { try { const storedData = await AsyncStorage.getItem(WATCHLIST_KEY); if (storedData) { const list = JSON.parse(storedData); setFavourites(list); // 判断当前电影是否已在清单中 const currentMovieInList = list.some(item => item.id === props.route.params.movieId); setIsFavourite(currentMovieInList); } } catch (err) { console.log('读取本地清单失败', err); } }; // 点击按钮时切换收藏状态 const toggleWatchlist = async () => { try { let newList = []; if (isFavourite) { // 已在清单中:移除当前电影 newList = favourites.filter(item => item.id !== details.id); } else { // 不在清单中:存入当前电影的必要展示字段,不要存全量详情浪费存储空间 const movieInfo = { id: details.id, title: details.title, poster_path: details.poster_path, vote_average: details.vote_average, release_date: details.release_date, overview: details.overview }; newList = [...favourites, movieInfo]; } // 先更新页面状态 setFavourites(newList); setIsFavourite(!isFavourite); // 同步持久化到本地存储 await AsyncStorage.setItem(WATCHLIST_KEY, JSON.stringify(newList)); } catch (err) { console.log('更新清单失败', err); } };
3. 页面加载时触发本地数据读取
修改你第一个拉取电影详情的useEffect,在详情数据加载完成后调用读取本地清单的方法:
useEffect(() => { const getDetails = async () => { const data = await GET(`/movie/${props.route.params.movieId}`); setDetails(data); setLoading(false); // 详情加载完成后读本地收藏数据 loadLocalWatchlist(); }; getDetails(); }, []);
4. 绑定收藏按钮事件
找到你现在写在返回按钮旁边、用nolicked.png图标的TouchableOpacity组件,替换成以下代码,绑定点击事件、根据状态切换图标:
<TouchableOpacity onPress={toggleWatchlist} style={{ marginLeft:20, marginTop: 20, marginBottom:20}} > <Image // 这里替换成你自己项目里的已收藏图标路径即可 source={isFavourite ? require("../../assets/icons/liked.png") : require("../../assets/icons/nolicked.png")} style={{ width:256/5.7 , height: 252/5.7 }} /> </TouchableOpacity>
观影清单页读取数据
单独做观影计划列表页时,只需要在对应页面的useEffect里用同样的key调用AsyncStorage.getItem(WATCHLIST_KEY),拿到数据JSON.parse之后,用FlatList渲染即可,和你现有热门电影列表的渲染逻辑完全一致。
注意:AsyncStorage仅支持存储字符串类型,所以存数组/对象时必须先用
JSON.stringify转成字符串,读取后再用JSON.parse转回结构化数据,否则会报错。对于你当前的入门项目,AsyncStorage完全够用,不需要引入更重的数据库方案。
内容的提问来源于stack exchange,提问作者SO KP

