如何在React+TypeScript中用useState实现仅点击图标变红
解决方案
问题根源在于你用了一个全局布尔值iconFavorite控制所有图标状态,所有图标都绑定同一个变量,所以状态一变全跟着变。要实现单个图标独立控制,得给每个列表项维护专属的收藏状态。
方法1:用对象存储已收藏的Item ID
把状态改成对象,用Item的ID作为键,记录每个Item的收藏状态:
import * as React from "react"; import { Box, Card, CardActionArea, CardActions, CardContent, CardMedia, Grid, Typography } from "@mui/material"; import FavoriteIcon from "@mui/icons-material/Favorite"; import { ButtonProps } from "./ButtonProps"; import data from "./data/data.json"; import { useState } from "react"; export default function ExemplesCard() { // 用对象存储已收藏的item ID,键为id,值为布尔值 const [favorites, setFavorites] = useState<Record<number, boolean>>({}); // 切换指定item的收藏状态 const toggleFavorite = (itemId: number) => { setFavorites(prevState => ({ ...prevState, [itemId]: !prevState[itemId] })); }; return ( <Box sx={{ flexGrow: 1, margin: "0 2rem" }}> <Grid container justifyContent="center" spacing={{ xs: 8, sm: 8, md: 8, lg: 8, xl: 8 }} className="GRID1" > {data.map((item) => { // 判断当前item是否被收藏 const isFavorite = favorites[item.id] || false; return ( <Grid item xs={12} sm={6} md={4} lg={3} xl={2} sx={{ display: "flex", justifyContent: "center", marginTop: "1rem" }} key={item.id} // 把key移到Grid组件上,符合React列表渲染规范 > <Card sx={{ p: "1rem", boxShadow: 4, maxWidth: { xs: "250px", sm: "250px", md: "280px", lg: "300px", xl: "300px" } }} > <CardActionArea> <CardMedia component="img" height="140" image={item.img} /> <CardContent> <Typography gutterBottom variant="h5" component="div"> {item.title} </Typography> <Typography variant="body2" color="text.secondary"> Lizards are a widespread group of squamate reptiles, with over 6,000 species, ranging across all continents except Antarctica </Typography> </CardContent> </CardActionArea> <CardActions> <ButtonProps size="small" endIcon={ <FavoriteIcon onClick={() => toggleFavorite(item.id)} // 传入当前item的id style={{ color: isFavorite ? "red" : "white" }} // 根据当前item的状态设置颜色 /> } > Favorite </ButtonProps> </CardActions> </Card> </Grid> ); })} </Grid> </Box> ); }
方法2:用Set存储收藏的ID
如果只需要记录已收藏的ID,用Set会更简洁:
// 初始化状态为Set const [favoriteIds, setFavoriteIds] = useState<Set<number>>(new Set()); // 切换收藏状态的函数 const toggleFavorite = (itemId: number) => { setFavoriteIds(prevSet => { const newSet = new Set(prevSet); newSet.has(itemId) ? newSet.delete(itemId) : newSet.add(itemId); return newSet; }); }; // 在渲染时判断当前item是否被收藏 const isFavorite = favoriteIds.has(item.id);
核心改动说明
- 把全局布尔状态替换为记录每个Item ID的状态集合(对象/Set)
- 点击事件传入当前Item的ID,仅切换该ID对应的状态
- 每个图标根据自身Item的状态判断颜色,不再依赖全局变量
内容的提问来源于stack exchange,提问作者Begginer
相关产品推荐
相关产品推荐

