phadaphunk
phadaphunk

Reputation: 13273

Modify image on div mouseover

I have a basic Card.

enter image description here

I want the image to change its src when I mouseover on the card. I can change the image when I mouseover on the <img/> tag itself like so :

<img src={item.iconUrl}
     onMouseOver={e => (e.currentTarget.src = item.iconHoverUrl)}
     onMouseOut={e => (e.currentTarget.src = item.iconHoverUrl)}
     className="mr-3 avatar-lg rounded" alt="app_icon" 
/>

But I don't find any way to reference this image's src when I'm out of it's scope. I tried setting the content of src into a variable and changing it's value on the card's mouseover but that won't trigger an update of the src of the image so it doesn't work either.

Here is the code of the component if it helps :

<Card className="app-hover" style={{ marginTop: '10px', height: '92%', overflow: 'hidden' }}>
<CardBody className="p-3">
    <Media>
        <img src={item.iconUrl}
            onMouseOver={e => (e.currentTarget.src = item.iconHoverUrl)}
            onMouseOut={e => (e.currentTarget.src = item.iconHoverUrl)}
            className="mr-3 avatar-lg rounded" alt="app_icon" />
        <Media body>
            <Row style={{ marginLeft: '4px', marginTop: '15px' }}>
                <h5 className="mt-1 mb-0">{this.props.i18n.language === 'en' ? item.title : item.titleFR}</h5>
            </Row>
        </Media>
    </Media>
    <Row>
        <Col lg={6}>
            <Media>
                <CreditCard className="icon-dual align-self-center mr-2"></CreditCard>
                <Media body>
                    <h5 className="mt-2 pt-1  font-size-16">{this.props.i18n.language === 'en' ? 'Not Owned' : 'Non-Acquis'}</h5>
                </Media>
            </Media>
        </Col>
        <Col lg={6}>
            <Media>
                <Users className="icon-dual align-self-center mr-2"></Users>
                <Media body>
                    <h5 className="mt-2 pt-1 font-size-16">
                        {
                            item.stats ? item.stats.users : ''
                        }
                    </h5>
                </Media>
            </Media>
        </Col>

    </Row>

    <Row className="mt-2 border-top pt-2" style={{ paddingLeft: '8px', paddingRight: '8px' }}>
        <p className="text-muted">{this.props.i18n.language === 'en' ? item.shortDescription : item.shortDescriptionFR}</p>
    </Row>
</CardBody>

Is it possible to do it the way I have it setup? As you can obviously see from the code, the image is fetched from an api and always changing so I can't simply hardcode the animation in CSS.

Upvotes: 2

Views: 59

Answers (2)

Ivan Mjartan
Ivan Mjartan

Reputation: 987

I will extract img into functional component. In Typescript something like.

import React from "react";
import { useState } from "react";

interface IMyImgProps{
    iconUrl: string;
    iconHoverUrl: string;
}

export const MyImg: React.FunctionComponent<IMyImgProps> = props => {
    const [icon, setIcon] = useState(props.iconUrl);

    const onMouseOver = () => setIcon(props.iconHoverUrl);
    const onMouseOut = () => setIcon(props.iconUrl);

    return <img src={icon} onMouseOver={onMouseOver} onMouseOut={onMouseOut} />
}

Upvotes: 1

Emanuele Scarabattoli
Emanuele Scarabattoli

Reputation: 4469

You should not try to change the DOM "directly", instead you should call a function that mutate the state and use the new icon from the state itself. Let me explain with an example:

const [icon, setIcon] = useState("");

const onMouseOver = () => setIcon("the-over-icon");

const onMouseOut = () => setIcon("the-not-over-icon");

// ...
<Card onMouseOver={onMouseOver} onMouseOut={onMouseOut}>
    <img src={icon} />
</Card>

Upvotes: 3

Related Questions