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

React中遍历元素时实现单个元素Hover效果的方案

React中map渲染卡片时悬停效果全局触发的解决方法

我在使用React的map函数渲染卡片列表时遇到了一个问题:鼠标悬停任意一张卡片,所有卡片都会触发悬停效果(显示“shop now”框),无法实现单张卡片独立的悬停交互。

原问题代码

const Card = () => {

    const [isHovering, setIsHovering] = useState(false);

    const handleMouseOver = () => {
        setIsHovering(true);
    };

    const handleMouseOut = () => {
        setIsHovering(false);
    };

    return (
        <>
            {productsList.map((product) => (
            <div key={product.id}>
                <div className="relative mb-4" onMouseOver={handleMouseOver} onMouseOut={handleMouseOut}>
                    <img src={product.img} alt="product" className="w-fit h-fit jshover cursor-pointer" />
                    {isHovering ? <CardOptions /> : ""}
                </div>
                <div className="flex justify-center flex-col px-3">
                    <h3 className="captialize font-sans font-bold text-black mb-3">Adicolor Classics Joggers</h3>
                    <div className="flex justify-between ">
                        <span className="capitalize font-normal font-sans text-[#777777]">Dress</span>
                        <span className="font-sans font-bold">$63.85</span>
                    </div>
                </div>
            </div>
            ))}
        </>
    )
}

问题原因

原代码中使用了一个全局布尔状态isHovering,所有通过map生成的卡片都共享这个状态。当任意一张卡片触发onMouseOver时,状态被设置为true,导致所有卡片的{isHovering ? <CardOptions /> : ""}条件渲染都生效,最终所有卡片同时显示悬停元素。

解决方案

将状态改为存储当前悬停卡片的索引(初始值设为-1,表示无卡片悬停),通过索引匹配来实现单张卡片的独立悬停控制:

const Card = () => {

const [isHovering, setIsHovering] = useState(-1);
const handleMouseOver = (item) => {
    setIsHovering(item);
};

const handleMouseOut = () => {
    setIsHovering(-1);
};


return (
    <>
        {productsList.map((product, index) => (
            <div key={product.id}>
                <div className="relative mb-4" onMouseOver={() => {
                    handleMouseOver(index);
                }} onMouseOut={handleMouseOut}>
                    <img src={product.img} alt="product" className="w-fit h-fit jshover cursor-pointer" />
                    {isHovering === index ? <CardOptions /> : ""}
                </div>
                <div className="flex justify-center flex-col px-3">
                    <h3 className="captialize font-sans font-bold text-black mb-3">{product.title}</h3>
                    <div className="flex justify-between ">
                        <span className="capitalize font-normal font-sans text-[#777777]">{product.category}</span>
                        <span className="font-sans font-bold">{product.price}</span>
                    </div>
                </div>
            </div>
        ))}
    </>
)
}

解决思路

  1. 将状态isHovering的类型从布尔值改为数字,初始值设为-1(表示没有卡片处于悬停状态)
  2. 在map遍历卡片时,同时获取当前卡片的index
  3. 鼠标悬停时,将当前卡片的index存入状态;鼠标移出时,重置状态为-1
  4. 条件渲染时,仅当当前卡片的index与状态中存储的索引匹配时,才显示悬停元素CardOptions

内容的提问来源于stack exchange,提问作者Hayytz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 00:45:46