Best way to change image and description onClick with react hooks

I have a list of services, being displayed beside the list is a picture and a description, basically when I click the list item I want the picture to change to the corresponding image/description. Right now I have the image changing onClick with hooks which is great but I’m not sure the best way to also change the descriptions. Should I make an object for each services which include the image src and then also the text? How would I go about doing that with react hooks? What would the onClick/object look like?

import React, { useState, useEffect } from "react"
import styles from "./Services.module.css"
import FadeInSection from "../FadeInSection/FadeInSection"
import { SRLWrapper } from "simple-react-lightbox"
import kitchen from "../../images/GalleryImages/image1.jpg"
import bathroom from "../../images/GalleryImages/image2.jpg"
import flooring from "../../images/GalleryImages/image4.jpg"
import painting from "../../images/GalleryImages/image5.jpg"
import cabinets from "../../images/GalleryImages/image6.jpg"
import backsplash from "../../images/GalleryImages/image7.jpg"
import basement from "../../images/GalleryImages/image8.jpg"

const Services = () => {
  const [selectedInterior, setSelectedInterior] = useState(kitchen)
  const [selectedExterior, setSelectedExterior] = useState(bathroom)

  return (
    <div className={styles.container} id="services-page">
      <div className={styles.content}>
        <FadeInSection>
          <div className={styles.description}>
            <h1 className="bigTitle">What we have to offer</h1>
            <h2 className="smallTitle">
              We offer a variety of services for both the interior and exterior
              of your home
            </h2>
            <div className="line"></div>
          </div>
          <SRLWrapper>
            <section className={styles.servicesSection}>
              <div className={styles.servicesContainer}>
                <div className={styles.servicesContent}>
                  <h1 className={styles.servicesTitle}>Interior Services</h1>
                  <ul className={styles.renovationList}>
                    <li onClick={() => setSelectedInterior(bathroom)}>
                      Bathrooms
                    </li>
                    <li onClick={() => setSelectedInterior(basement)}>
                      Basements
                    </li>
                    <li onClick={() => setSelectedInterior(kitchen)}>
                      Kitchens
                    </li>
                    <li onClick={() => setSelectedInterior(cabinets)}>
                      Cabinet Installation
                    </li>
                    <li onClick={() => setSelectedInterior(painting)}>
                      Painting
                    </li>
                    <li onClick={() => setSelectedInterior(backsplash)}>
                      Backsplash
                    </li>
                    <li onClick={() => setSelectedInterior(flooring)}>
                      Flooring
                    </li>
                  </ul>
                </div>
              </div>
              <div className={styles.service}>
                <div className={styles.imageContainer}>
                  <img
                    src={selectedInterior}
                    className={styles.interiorImage}
                  />
                </div>
                <p className={styles.serviceDescription}>
                  Lorem ipsum dolor sit amet consectetur adipisicing elit. Enim
                  perferendis quibusdam ipsa fuga qui, velit non voluptatem,
                  quod, illum tempore consequuntur! Fuga fugiat odit quisquam
                  officia consequuntur, sapiente voluptatibus maxime!
                </p>
              </div>
            </section>
            <section className={styles.servicesSection}>
              <div className={styles.servicesContainer}>
                <div className={styles.servicesContent}>
                  <h1 className={styles.servicesTitle}>Exterior Services</h1>
                  <ul className={styles.renovationList}>
                    <li onClick={() => setSelectedExterior(kitchen)}>
                    Fences
                    </li>
                    <li onClick={() => setSelectedExterior(bathroom)}>
                     Decks
                    </li>
                    <li onClick={() => setSelectedExterior(flooring)}>
                      Patios
                    </li>
                    <li onClick={() => setSelectedExterior(kitchen)}>
                      Porches
                    </li>
                    <li onClick={() => setSelectedExterior(bathroom)}>
                      Siding
                    </li>
                  </ul>
                </div>
              </div>
              <div className={styles.service}>
              <div className={styles.imageContainer}>
                <img src={selectedExterior} className={styles.exteriorImage} />
              </div>
                <p className={styles.serviceDescription}>
                  Lorem ipsum dolor sit amet consectetur adipisicing elit. Enim
                  perferendis quibusdam ipsa fuga qui, velit non voluptatem,
                  quod, illum tempore consequuntur! Fuga fugiat odit quisquam
                  officia consequuntur, sapiente voluptatibus maxime!
                </p>
             </div>
            </section>
          </SRLWrapper>
        </FadeInSection>
      </div>
    </div>
  )
}

export default Services

localhost picture
code section picture

1 thought on “Best way to change image and description onClick with react hooks”

  1. Setting an object with both the image and text like you suggested would be a very reasonable suggestion. Then, your state can hold that entire object. Here’s a very basic/minimal example demonstrating how that could work:

    const Rooms = {
      kitchen: {
        img: "kitchenImage",
        text: "kitchenText"
      },
      bedroom: {
        img: "bedroomImage",
        text: "bedroomText"
      }
    }
    
    export default function App() {
      const [selectedRoom, setSelectedRoom] = React.useState()
    
      return (
        <div className="App">
          <div>
           {selectedRoom ? 
             <div>
               Image: {selectedRoom.img}<br/>
               Text: {selectedRoom.text}
             </div> 
           : null}
          </div>
          <ul>
           <li style={selectedRoom === Rooms.kitchen ? {fontWeight: "bold"} : {}} 
               onClick={() => setSelectedRoom(Rooms.kitchen)}>kitchen</li>
           <li style={selectedRoom === Rooms.bedroom ? {fontWeight: "bold"} : {}} 
               onClick={() => setSelectedRoom(Rooms.bedroom)}>bedroom</li>
          </ul>
        </div>
      );
    }
    

    It starts with nothing selected, but you could easily start with a default selection by doing something like:

    ... = React.useState(Rooms.bedroom)
    

    Using this system, you’ll be able to add more fields if needed to Rooms as you go, without adding additional state variables.

    Update in response to comments:
    I added a style attribute to the li that changes based on selection. In a real-world example, it would may be worth abstracting the li into its own component, but doing things this way serves this minimal example.

    Reply

Leave a Comment