I am new to React. My issue is that I am trying to change the background color of a div that I dynamically render in React. To do this I learned about useRef() to single out the element.
If I do a console.log() in the onHover function, the log works in the browser, but the background color of the element does not change for some reason, even though I have implemented useRef how others have for this exact same reason.
Thank you in advance for your help, here is the code:
import React, { useRef } 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 liItem = useRef(null)
const onHover = () => {
liItem.current.style.backgroundColor = 'cornflowerblue'
}
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 ref={liItem} key={county} style={liItemContainer} onm ouseOver={onHover}>
<li style={liStyle}>{county}</li>
</div>
)
})
return (
<ul style={ulStyle}>
{countiesListItems}
</ul>
)
}
export default CountiesList;
CodePudding user response:
That's because you use a single ref
on an array of elements, You need to use an array of template refs
or just pass the target element by onMouseOver={(e) => onHover(e.target)}
and change the style
directly without the need to template refs
import React, { useRef } 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 liItem = useRef(null)
const onHover = (element) => {
element.style.backgroundColor = 'cornflowerblue'
}
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 ref={liItem} key={county} style={liItemContainer} onm ouseOver={(e) => onHover(e.target)}>
<li style={liStyle}>{county}</li>
</div>
)
})
return (
<ul style={ulStyle}>
{countiesListItems}
</ul>
)
}
export default CountiesList;
CodePudding user response:
If you really want to do your hover effect "in software" (i.e. not with CSS, which is much more preferred for a purely visual effect), then the React way is to use state, not refs.
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"
};
const liStyle = {
fontWeight: "700"
};
const counties = [
"Antrim",
"Armagh",
"Carlow",
"Cavan",
// ...
];
const CountiesList = () => {
const [hoveredCounty, setHoveredCounty] = React.useState(null);
const onHover = (event) => {
setHoveredCounty(event.currentTarget.dataset.county);
};
return (
<ul style={ulStyle}>
{counties.map((county) => (
<div
data-county={county}
key={county}
style={{
...liItemContainer,
background: hoveredCounty === county ? "orange" : "#a9c4f5"
}}
onm ouseOver={onHover}
>
<li style={liStyle}>{county}</li>
</div>
))}
</ul>
);
};