You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 20:54:06