Search code examples
javascriptreactjsnext.jsgsapuse-ref

Display image dynamically on hover on title with Nextjs and GSAP


I have a list of title dynamically rendered and I want to display an image when I hover over each title. When I hover a title, all the images display. I'm still a rookie on React. I think the solution is simple, but I don't find it.

Component.js

import React, { useEffect, useRef } from "react";
import { Row, Col } from "react-bootstrap"
import Link from "next/link";
import gsap from "gsap";
import { getStrapiMedia } from "../lib/media";


const Articles = ({ articles }) => {

  const itemsRef = useRef({});

  const handleHover = (e) => {
    gsap.to(".imgHome", {
      display: "block"
    })
  }

  const handleHoverExit = (e) => {
    gsap.to(".imgHome", {
      display: "none"
    })
  }

  return (
    <div>
      <div className="tableau">
            {articles.map((item) => (
              <Row key={item.id}
                onMouseEnter={(e) => handleHover(e)}
                onMouseOut={(e) => handleHoverExit(e)}
                ref={el => (itemsRef.current[item.id] = el)}>
                <Link href={`/article/${item.id}`}>
                  <a className="titre"
                  >{item.title} </a>
                </Link>
                <img className="imgHome" src={getStrapiMedia(item.image.url)}
                  width="800" />
              </Row>
            ))}
      </div>
    </div>
  )
}

export default Articles

Solution

  • You can use refs on the <img> elements, then reference them in gsap.to function call rather than using the .imgHome class.

    const Articles = ({ articles }) => {
        const imagesRef = useRef({});
    
        const handleHover = (e, id) => {
            gsap.to(imagesRef.current[id], { display: "block" })
        }
    
        const handleHoverExit = (e, id) => {
            gsap.to(imagesRef.current[id], { display: "none" })
        }
    
        return (
            <div>
                <div className="tableau">
                    {articles.map((item) => (
                        <Row key={item.id}
                            onMouseEnter={(e) => handleHover(e, item.id)}
                            onMouseOut={(e) => handleHoverExit(e, item.id)}
                        >
                            <Link href={`/article/${item.id}`}>
                                <a className="titre">{item.title} </a>
                            </Link>
                            <img 
                                ref={(el) => (imagesRef.current[item.id] = el)} 
                                className="imgHome" 
                                src={getStrapiMedia(item.image.url)} 
                                width="800" 
                            />
                        </Row>
                    ))}
                </div>
            </div>
        )
    }