如何使用useState Hook为每个列表项单独实现hover时图片隐藏的交互
问题根因
现在所有列表项联动失效的核心原因:你在Wrap组件层定义的visible是全局共享的单个布尔值,所有渲染出来的图片节点的className判断都读这一个值,只要触发一次状态更新,所有节点的显示样式会同步变化,根本做不到单节点独立控制。
修复逻辑
弃用“全局布尔值存是否显示”的写法,改成「用状态记录当前需要隐藏的列表项的唯一标识」:
- 状态默认值存
null,代表没有任何图片处于隐藏状态;hover某一项时,把该项的索引(你现在的JSON没有唯一id,用map循环拿到的index完全够用)存进状态;鼠标移开时把状态改回null - 每个图片节点判断是否隐藏的逻辑,只对比“自己的索引”和“状态存的索引”是否匹配,匹配才加隐藏类名,完全不会影响其他节点
修正后的完整可运行代码
import React, { useState } from 'react'; import styled from "styled-components"; import partnerIcons from './json/partnersIcon.json'; const Icorn = styled.img` padding:4px; vertical-align:middle; display:block; &.hidden { display:none; } ` // 补上你原代码漏定义的Li组件,避免React报未定义组件的错误 const Li = styled.li` list-style: none; ` const Ul = styled.ul` width:75%; display:grid; grid-template-columns:190px 190px 190px 190px 190px; margin: 0 auto; padding: 0; @media ${({ theme }) => theme.device.tablet} { display:none; } ` const Wrap =()=>{ // 状态替换:不再存全局布尔值,改为记录当前需要隐藏的项的索引,默认null代表没有项隐藏 const [activeHiddenIndex, setActiveHiddenIndex] = useState(null); const pIcornWrap = partnerIcons.map((item, index)=>{ return( <Li key={index}> <Icorn src ={item.image} // 鼠标移入时,把当前项的索引存进状态,触发对应项隐藏 onMouseEnter={()=> setActiveHiddenIndex(index)} // 鼠标移出时,清空状态,所有项恢复显示 onMouseLeave={()=> setActiveHiddenIndex(null)} // 只有当前索引和状态记录的索引匹配时,才加隐藏类名 className={activeHiddenIndex === index ? 'hidden' : 'show'} > </Icorn> </Li> ) }); return( <div> <Ul> {pIcornWrap} </Ul> <MobileView><PartnersPage/></MobileView> </div> ) }
补充优化点
- 原代码里绑定的
onMouseOver/onMouseDown事件不符合hover交互的预期,已经替换为标准的onMouseEnter(鼠标移入)、onMouseLeave(鼠标移出)事件对,实现移入隐藏、移出自动恢复的效果 - 如果后续需要支持多个图片同时处于隐藏状态,只要把存单个索引的状态改成存索引集合(比如用Set存储),hover进入时向集合加入当前索引,移出时从集合删除对应索引即可
内容的提问来源于stack exchange,提问作者behappy8
相关产品推荐
相关产品推荐

