React中map渲染的收藏按钮点击单个后全部变色如何解决?
问题根因
你当前在AnimeList组件内定义的favorite是全组件共享的布尔状态,所有通过map遍历渲染的收藏按钮都依赖这同一个状态判断类名,只要状态修改就会触发所有按钮同步变化,这是状态绑定粒度的问题,和map用法本身无关。
修复方案
把状态修改为存储已收藏内容的mal_id集合,每个按钮仅判断当前遍历项的id是否在集合内,即可单独控制自身的类名切换。
修改后的完整代码如下:
import { Link } from "react-router-dom"; import { useState } from "react"; import 'font-awesome/css/font-awesome.min.css'; import "./App.css"; import DBRequest from "./DBRequest"; const AnimeList = ( { results } ) => { // 状态改为存储已收藏的mal_id集合,判断存在的时间复杂度为O(1) const [favoritedIds, setFavoritedIds] = useState(new Set()); const toggleFavorite = (mal_id) => { const data_mal_id = { mal_id }; // 基于前一次的状态修改,避免并发更新问题 setFavoritedIds(prev => { const newFavorited = new Set(prev); if (newFavorited.has(mal_id)) { // 已收藏,执行取消逻辑 newFavorited.delete(mal_id); DBRequest(`/api/favorite/delete/${mal_id}`, "DELETE", data_mal_id); } else { // 未收藏,执行添加逻辑 newFavorited.add(mal_id); DBRequest(`/api/favorite/post`, "POST", data_mal_id); } return newFavorited; }) } return ( <div className="anime-list flex overflow-auto no-scrollbar"> { results && results.map((result) => ( <div className="anime-preview p-3" key={ result.mal_id }> <div className="group w-48 h-72 relative cursor-none"> <img className="object-cover absolute h-full w-full z-10 filter group-hover:blur-sm group-hover:opacity-50" src={ result.image_url } alt="" /> <h2 className="absolute w-full top-0 text-left p-2 font-bold text-base z-20 pointer-events-none opacity-0 group-hover:opacity-100">{ result.type }</h2> <h2 className="absolute w-full top-1/4 text-center font-bold text-base z-20 pointer-events-none opacity-0 group-hover:opacity-100">{ result.title }</h2> {/* 注意不要在map循环里写重复的id,id是全局唯一的,改为class */} <span className="heart"> <button onClick={ () => toggleFavorite(result.mal_id) }> {/* 只判断当前项的mal_id是否在收藏集合里 */} {favoritedIds.has(result.mal_id) ? ( <i className="fa fa-heart absolute top-0 right-0 p-2 font-bold text-base z-20 opacity-0 group-hover:opacity-100" aria-hidden="true" > </i> ) : ( <i className="fa fa-heart-o absolute top-0 right-0 p-2 font-bold text-base z-20 opacity-0 group-hover:opacity-100" aria-hidden="true" > </i> )} </button> </span> </div> </div> )) } </div> ); }
补充说明
如果你的后端提供了获取当前用户已收藏列表的接口,可以在组件挂载时调用接口,把返回的mal_id数组转成Set作为favoritedIds的初始值,这样页面加载时就能正确回显已收藏状态。
内容的提问来源于stack exchange,提问作者Mirana
相关产品推荐
相关产品推荐

