React开发Pokedex宝可梦图鉴 实现添加/移除收藏列表功能求助
核心问题梳理
你当前的收藏状态只存储在PokemonFav组件内部,属于组件私有状态,详情页、导航栏等其他组件无法访问和修改,所以无法实现跨页面的收藏交互。
具体改造步骤
1. 新建全局收藏Context实现状态共享
在src目录下新建FavContext.js文件,代码如下:
import { createContext, useContext, useState, useEffect } from 'react'; const FavContext = createContext(); export function FavProvider({ children }) { // 初始化从localStorage读取收藏列表,避免刷新丢失 const [favList, setFavList] = useState(() => { const saved = localStorage.getItem('pokemonFav'); return saved ? JSON.parse(saved) : []; }); // 收藏列表变更时自动同步到localStorage useEffect(() => { localStorage.setItem('pokemonFav', JSON.stringify(favList)); }, [favList]); // 切换收藏状态:已收藏则移除,未收藏则添加 const toggleFav = (pokemon) => { setFavList(prev => { // 用宝可梦id作为唯一判断标准,避免重名问题 const isExist = prev.find(item => item.id === pokemon.id); if (isExist) { return prev.filter(item => item.id !== pokemon.id); } else { return [...prev, pokemon]; } }) } // 判断某个宝可梦是否已收藏 const isFavorited = (pokemonId) => { return favList.some(item => item.id === pokemonId); } return ( <FavContext.Provider value={{ favList, toggleFav, isFavorited }}> {children} </FavContext.Provider> ) } // 自定义hooks,方便其他组件调用context export function useFav() { return useContext(FavContext); }
2. 全局注入Context
修改App.jsx,用FavProvider包裹所有路由组件:
import { FavProvider } from './FavContext'; function App() { // 你原有App组件的逻辑不变,只需要在最外层包FavProvider return ( <FavProvider> {/* 你原有所有的路由、导航栏、页面组件都放在这里 */} </FavProvider> ) }
3. 修改详情页收藏按钮逻辑
在宝可梦详情页组件中引入useFav,修改按钮代码:
import { useFav } from '../FavContext'; // 组件内部逻辑 function PokemonDetail() { // 你原有获取当前宝可梦数据的逻辑不变,假设当前宝可梦数据存在currentPokemon变量里 const { toggleFav, isFavorited } = useFav(); const isFav = isFavorited(currentPokemon.id); return ( {/* 其他详情内容不变 */} <button onClick={() => toggleFav(currentPokemon)}> {isFav ? '取消收藏' : '添加收藏'} </button> ) }
如果要在宝可梦列表卡片pokemoncard.js上加收藏按钮,逻辑和详情页完全一致,直接调用toggleFav和isFavorited方法即可。
4. 改造你的PokemonFav组件
直接从全局Context获取收藏列表渲染,新增移除功能:
import { useFav } from '../FavContext'; function PokemonFav(){ const { favList, toggleFav } = useFav(); return( <div> <h2>收藏列表</h2> {favList.length === 0 ? ( <p>暂无收藏的宝可梦</p> ) : ( <ul> {favList.map(pokemon=> ( <li key={pokemon.id}> {pokemon.name} <button onClick={() => toggleFav(pokemon)}>移除收藏</button> </li> ))} </ul> )} </div> ) } export default PokemonFav;
5. 导航栏收藏入口
导航栏直接添加跳转到收藏页面的路由即可,收藏页已经可以直接读取全局的收藏列表渲染。
内容的提问来源于stack exchange,提问作者Yasmins
相关产品推荐
相关产品推荐

