React中useRef()结合onMouseOver修改div背景色失效问题
问题原因
你用单个useRef绑定到循环生成的所有<div>上,每次循环都会覆盖这个ref的指向,最终liItem.current只会指向最后一个生成的<div>元素。所以当你hover任意元素时,实际修改的是最后一个元素的背景色,而不是当前hover的那个,看起来就像样式没生效。
解决方案
有几种更简单的方式实现hover变色,完全不需要依赖useRef:
方法1:通过事件对象获取当前元素
修改onHover函数,利用事件参数e直接拿到触发hover的元素:
const onHover = (e) => { e.currentTarget.style.backgroundColor = 'cornflowerblue'; }
循环里的元素绑定事件无需额外修改,事件会自动传递参数:
<div key={county} style={liItemContainer} onMouseOver={onHover}>
如果需要鼠标移出时还原颜色,再添加一个onMouseOut事件:
const onMouseOut = (e) => { e.currentTarget.style.backgroundColor = '#a9c4f5'; } // 绑定到元素上 <div key={county} style={liItemContainer} onMouseOver={onHover} onMouseOut={onMouseOut}>
方法2:使用CSS:hover伪类(推荐)
用CSS处理hover状态是最简洁高效的方式,还能自动处理鼠标移出的样式还原:
/* 可以在组件内添加style标签,或单独的CSS文件 */ .county-item { height: 50px; padding-left: 15px; display: flex; align-items: center; background-color: #a9c4f5; } .county-item:hover { background-color: cornflowerblue; }
然后把元素的内联样式替换为className:
<div key={county} className="county-item"> <li style={liStyle}>{county}</li> </div>
方法3:React状态控制(适合复杂交互场景)
如果需要跟踪当前hover的元素做更多逻辑,可以用状态记录hover的区县名称,动态设置样式:
import React, { useState } from "react"; // ...其他代码不变 const [hoveredCounty, setHoveredCounty] = useState(null); const onHover = (county) => { setHoveredCounty(county); }; const onMouseOut = () => { setHoveredCounty(null); }; // 循环时动态生成样式 let countiesListItems = counties.map(county => { const containerStyle = { ...liItemContainer, backgroundColor: hoveredCounty === county ? 'cornflowerblue' : liItemContainer.backgroundColor }; return ( <div key={county} style={containerStyle} onMouseOver={() => onHover(county)} onMouseOut={onMouseOut} > <li style={liStyle}>{county}</li> </div> ); });
修复后的完整代码(方法1示例)
import React from "react"; const CountiesList = () => { const counties = [ 'Antrim', 'Armagh', 'Carlow', 'Cavan', 'Clare', 'Cork', 'Derry', 'Donegal', 'Down', 'Dublin', 'Fermanagh', 'Galway', 'Kerry', 'Kildare', 'Kilkenny', 'Laois', 'Leitrim', 'Limerick', 'Longford', 'Louth', 'Mayo', 'Meath', 'Monaghan', 'Offaly', 'Roscommon', 'Sligo', 'Tipperary', 'Tyrone', 'Waterford', 'Westmeath', 'Wexford', 'Wicklow' ] const onHover = (e) => { e.currentTarget.style.backgroundColor = 'cornflowerblue' } const onMouseOut = (e) => { e.currentTarget.style.backgroundColor = '#a9c4f5' } const ulStyle = { listStyleType: 'none', paddingInlineStart: 0, margin: 0, width: '100%', height: '300px', overflowY: 'scroll', borderBottomLeftRadius: '12px' } const liItemContainer = { height: '50px', paddingLeft: '15px', display: 'flex', alignItems: 'center', backgroundColor: '#a9c4f5' } const liStyle = { fontWeight: '700' } let countiesListItems = counties.map(county => { return ( <div key={county} style={liItemContainer} onMouseOver={onHover} onMouseOut={onMouseOut}> <li style={liStyle}>{county}</li> </div> ) }) return ( <ul style={ulStyle}> {countiesListItems} </ul> ) } export default CountiesList;
内容的提问来源于stack exchange,提问作者Brandon
相关产品推荐
相关产品推荐

