React useState状态异常:收藏游戏数组无法累加问题求助
问题描述
我正在开发一个类似rawg.io的游戏发现网站,通过rawg API获取游戏数据并映射到Chakra Card组件。组件内设有收藏按钮,点击后将游戏存入favoriteGames数组,用于展示收藏列表。
代码示例:
interface Game { id: number; name: string; } const [favoriteGames, setFavoriteGames] = useState<Game[]>([]); let game = {id: 1, name: 'Portal 2'} /* 示例:当前点击收藏的游戏 */ const handleFavourite = (isFavorite: boolean) => { if (isFavorite) { setFavoriteGames([...favoriteGames, game]); console.log(favoriteGames); } };
点击收藏Portal 2后,控制台显示数组包含该游戏,但再收藏GTA V时,数组仅保留GTA V。我怀疑每个游戏对应独立状态变量,但无法解决。本人是React新手,首次独立优化网站,求助解决该问题。
解决方案
你的问题出在状态更新的闭包陷阱,以及game变量的作用域问题,以下是具体修复步骤:
1. 使用函数式更新获取最新状态
React的setState是异步的,直接用favoriteGames旧状态值更新时,会因为闭包捕获旧值导致多次更新覆盖内容。改用函数式更新,每次基于最新状态修改:
const handleFavourite = (isFavorite: boolean, currentGame: Game) => { if (isFavorite) { setFavoriteGames(prevFavorites => { // 先判断游戏是否已存在,避免重复添加 const isAlreadyAdded = prevFavorites.some(game => game.id === currentGame.id); if (!isAlreadyAdded) { return [...prevFavorites, currentGame]; } return prevFavorites; }); } else { // 可选:处理取消收藏逻辑 setFavoriteGames(prevFavorites => prevFavorites.filter(game => game.id !== currentGame.id) ); } };
2. 传递正确的当前游戏
不要用全局let game变量,渲染每个Chakra Card时,把当前遍历到的游戏作为参数传给handleFavourite:
{games.map(game => ( <Card key={game.id}> <CardBody> <Heading size="md">{game.name}</Heading> <Button onClick={() => { const isFavorite = favoriteGames.some(fav => fav.id === game.id); handleFavourite(!isFavorite, game); }} > {favoriteGames.some(fav => fav.id === game.id) ? '取消收藏' : '加入收藏'} </Button> </CardBody> </Card> ))}
3. 正确查看更新后的状态
之前的console.log(favoriteGames)会打印旧状态(因为setState异步),可以用useEffect监听状态变化:
useEffect(() => { console.log('更新后的收藏列表:', favoriteGames); }, [favoriteGames]);
修改后,多次收藏不同游戏时,数组会正确累加,不会出现覆盖情况。
内容的提问来源于stack exchange,提问作者Ahmed salem
相关产品推荐
相关产品推荐

