Home > front end >  React useRef() not working onMouseOver to change backgroundColor of div
React useRef() not working onMouseOver to change backgroundColor of div

Time:09-06

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>
  );
};
  • Related