Change image on hover in JSX
Asked Answered
B

6

16

How do I change an image on hover in JSX

I'm trying something like this:

<img src={require('../../../common/assets/network-inactive.png')}
onMouseOver={this.src = require('../../../common/assets/network.png')}
onMouseOut={this.src = require('../../../common/assets/network-inactive.png')} />
Businesslike answered 9/2, 2018 at 10:15 Comment(0)
M
48

I will assume you are writing this code in a React component. Such as:

class Welcome extends React.Component {
  render() {
    return (
       <img src={require('../../../common/assets/network-inactive.png')}
       onMouseOver={this.src = require('../../../common/assets/network.png')}
       onMouseOut={this.src = require('../../../common/assets/network-inactive.png')} 
       />
    );
  }
}

Targeting this.src will not work in this case as you are essentially looking for something named src in your class. For instance this.src could find something like this:

src = () => (alert("a source"))

But that is not what you want to do. You want to target the image itself.

Therfore you need to enter the <img /> context. You can do that easily like this:

 <img
    onMouseOver={e => console.log(e)}
  />

From there you can target the currentTarget property, among others. This will enter the context of your element. So now you can do something like this:

  <img
    src="img1"
    onMouseOver={e => (e.currentTarget.src = "img2")}
  />

The same can be done for onMouseOut.

You can use this same method on your other elements, as you will certainly need to do this again. But be careful as this is a not the only solution. On bigger projects you may want to consider using a store (Redux), and passing props rather than mutating elements.

Minimus answered 9/2, 2018 at 10:46 Comment(4)
Thank you, this is exactly what I realized later. I rather went with the CSS way to tackle the problem. Yes I am using redux in the project and I will implement your suggestion.Businesslike
You're welcome @new-boy-in-web-dev-business :) I'm happy for you.Minimus
@TypeKev So in which case this.src will work ? Looking for your comment forward.Squint
@hardy, sorry I just saw your reply now. I'm a bit late, but in this case, to accomplish the mutation of props within the img context, you would need to write a function called src that basically does what @ new-boy-in-web-dev-business is doing inline. i.e have a function named src whithin your class: src = ({ currentTarget: { src } }) => src = "img2". This will accomplish the same thing - set the src of currentTarget (which is the img element) to 'img2' :)Minimus
B
13

Best is to manage this in the state:

class App extends Component {
  state = {
    img: "https://i.vimeocdn.com/portrait/58832_300x300"
  }

  render() {
    return (
      <div style={styles}>
        <img
          src={this.state.img}
          onMouseEnter={() => {
            this.setState({
              img: "http://www.toptipsclub.com/Images/page-img/keep-calm-and-prepare-for-a-test.png"
            })
          }}

          onMouseOut={() => {
            this.setState({
              img: "https://i.vimeocdn.com/portrait/58832_300x300"
            })
          }}
        />
      </div>
    )
  }
};

https://codesandbox.io/s/5437qm907l

Brattice answered 9/2, 2018 at 10:49 Comment(1)
Mine is a stateless component (Functional Component).Businesslike
H
5

Another non-class approach:

import arrow from "../images/arrow.svg";
import arrowHover from "../images/arrowHover.svg";

function Arrow() {
  const [over, setOver] = useState(false);
  return (
    <div
      onMouseOver={() => setOver(true)}
      onMouseOut={() => setOver(false)}
    >
         <img
          src={over ? arrowHover : arrow}
          alt="arrow"
          width="50"
          height="50"
        />
    </div>   
  )
}
Hickory answered 7/12, 2021 at 16:6 Comment(0)
D
2

Here's a non-class approach using a functional component and typescript:

interface IconProps {
  src?: string;
  srcOnHover?: string;
  alt?: string;
}

const Icon: React.FC<IconProps> = ({ src, srcOnHover, alt }) => (
  <img
    src={src}
    alt={alt}
    onMouseOver={(e): void => {
      srcOnHover && (e.currentTarget.src = srcOnHover);
    }}
    onMouseOut={(e): void => {
      srcOnHover && (e.currentTarget.src = src || '');
    }}
  />
);

It can be used like that:

<Icon src="path/to/image.png" srcOnHover="path/to/hover-image.png" alt="Description" />
Dygal answered 30/7, 2020 at 8:1 Comment(0)
R
0

Here is a good one for handling image src in React with onMouseEnter and onMouseLeave. Contributing this non class based component version.

   import React, { useState } from 'react';
   
   function imageHoveControl({) {
     let imageVar = {
       nonhovered: '/public/image.jpg'
       hovered: '/public/imageHover.jpg'
     }
        let selectorDown = imageVar.nonhovered.src
        let selectorUp = imageVar.hovered.src
        //Pop "up" to meet cursor on hover 
        const [selectorImage, setSelectorImage] = useState(selectorDown);

        function handleMouseEnter() {
          setSelectorImage(selectorUp)
        }
        function handleMouseLeave() {
          setSelectorImage(selectorDown)
        }

          return (
              <img
                className="rounded-full h-14 w-14 sm:h-20 sm:w-20 bg-contain mx-1"
                src={selectorImage}
                onMouseEnter={handleMouseEnter}
                onMouseLeave={handleMouseLeave}
              />
          )
        }
Rainier answered 29/2 at 21:0 Comment(0)
F
-2

simple way to do this:

class Home extends React.Component { state = { icon: ICON_ONE }

render(){ return( <img src={this.state.icon} onMouseOver={()=>this.setState({icon:ICON_TWO})}
onMouseOut={() => this.setState({ icon: ICON_ONE })} /> ) }

Frimaire answered 12/3, 2021 at 7:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.