javascriptreactjsstyled-componentsreact-icons

Display text when hovering over an icon using React-Icon Library


so I am attempting to display text when you hover over a mouse. I am using React-Icons library and for styling using Styled-Components

I have 4 icons on my navbar - Home - About - Skills - Work

Each button is its own component in order for the hover to work properly so when i hover over 1 icon it doesnt display the text for all of them

import React, { useState } from 'react';
import { SkillsButton } from './SkillsBtnElements'

const SkillsBtn = () => {
  const [hover, setHover] = useState(false);
  const onHover = () => {
    setHover(!hover)
  }

  return (
    <div onMouseEnter={onHover} onMouseLeave={onHover} role="button" tabIndex='-3' >
      { hover ? "SKILLS" : <SkillsButton /> }
    </div>
  )
}

export default SkillsBtn;

And for styling i have

import styled from 'styled-components';
import { GiGearHammer } from 'react-icons/gi';

export const SkillsButton = styled(GiGearHammer)`
  font-size: 1.75rem;
  color: white;
  flex-grow: 1;
  cursor: pointer;
  @media screen and (max-width: 960px) {
    transition: all 0.2s ease-in-out;
    font-size: 1rem;
    color: white;
  }
  &:hover {
    transition: all 0.2s ease-in-out;
  }
`;

I do achieve a hover effect, but when I constantly hover the icon the logic seems to get messed up bc then its only the text that appears and when i hover over the text the icon appears...which isn't the desired effect

Example: https://gph.is/g/4ARQoRV


Solution

  • The abnormal effect is due to the stale closure problem. {hover ? "SKILLS" : <SkillsButton />} is being rendered with a stale value of hover. If you want the text to only appear when the mouse is over the div, try creating two separate functions for onMouseEnter and onMouseLeave events. Like this:

    import React, { useState } from "react";
    import { SkillsButton } from './SkillsBtnElements'
    
    const SkillsBtn = () => {
      const [hover, setHover] = useState(false);
      const onHover = () => {
        setHover(true);
      };
    
      const onLeave = () => {
        setHover(false);
      };
      return (
        <div
          onMouseEnter={onHover}
          onMouseLeave={onLeave}
          role="button"
          tabIndex="-3"
        >
          {hover ? "SKILLS" : <SkillsButton />}
        </div>
      );
    };
    
    export default SkillsBtn;