Prevent sibling divs from being affected by onClick events in React

Currently, I am facing an issue with changing the className of a specific div element when clicked. Whenever I click on one div, the classNames of all the div elements change. This problem arose from converting a vanilla JS concept into a React component. I am struggling to figure out what's wrong and how to prevent the onClick event from affecting sibling divs. Any help or guidance on this matter would be greatly appreciated. Here is my current code:

import React, { useState} from "react";

import { Panels } from "../../components/index";
import { data } from "../../constants/index";
import "./gallery.css";

const Gallery = () => {
  const [isOpen, setIsOpen] = useState(false);

    const toggleOpen = () => {
        setIsOpen(!isOpen);
    };
    
  return (
    <div className="panels">
      {data.restaurants.map((restaurant, index) => (
        <div
          className={`panel panel${index} ${isOpen ? "open open-active" : ""}`}
          onClick={toggleOpen}
        >
          <Panels
            key={restaurant.name + index}
            description={restaurant.description}
            name={restaurant.name}
            website={restaurant.website}
          />
        </div>
      ))}
    </div>
  );
};

export default Gallery;

This is my Panels Component code:

import React from "react";

const Panels = ({ name, description, website }) => {
    return (
  <div className="panel_text">
    <p>{description}</p>
    <p>{name}</p>
    <a href={website}>
      <p>Visit {name}</p>
    </a>
  </div>
)};

export default Panels;

And here is my CSS code:

*, *:before, *:after {
    box-sizing: inherit;
}

.panels {
    min-height: 100vh;
    overflow: hidden;
    display: flex;
}

.panel, .panel_text {
    background: '#fff';
    box-shadow: inse 0 0 0 5px rgba(255, 255, 255, 0.1);
    color: var(--color-golden);
    text-align: center;
    align-items: center;
    transition:
        font-size 0.7s cubic-bezier(0.61, -0.19, 0.7, -0.11),
        flex 0.7s cubic-bezier(0.61, -0.19, 0.7, -0.11);
    font-size: 20px;
    background-size: cover;
    background-position: center;
    flex: 1;
    justify-content: center;
    display: flex;
    flex-direction: column;
}
  
/* Remaining CSS styles removed for brevity */  

@media only screen and (max-width: 600px) {
    .panel p {
        font-size: 1rem;
    }
}

Answer №1

The current implementation saves a boolean value to determine if a div element is open or closed. However, this approach does not account for identifying which specific div element is open. To address this issue, it is recommended to save the index of the div element instead of using a boolean value.

By utilizing the index of the div element, you can easily identify and manage the state of each individual div element. Here's an example code snippet demonstrating how to implement this:

import React, { useState} from "react";
import { Panels } from "../../components/index";
import { data } from "../../constants/index";
import "./gallery.css";

const Gallery = () => {
  const [openIndex, setOpenIndex] = useState(null);
    
  return (
    <div className="panels">
      {data.restaurants.map((restaurant, index) => (
        <div
          className={`panel panel${index} ${openIndex === index ? "open open-active" : ""}`}
          onClick={() => setOpenIndex(index)}
        >
          <Panels
            key={restaurant.name + index}
            description={restaurant.description}
            name={restaurant.name}
            website={restaurant.website}
          />
        </div>
      ))}
    </div>
  );
};

export default Gallery;

Answer №2

It is important to have a unique value for isOpen state in each div element, as the state is shared among all divs.

To resolve this issue, you can convert the isOpen state into an object like the following example:

import React, { useState} from "react";

import { Panels } from "../../components/index";
import { data } from "../../constants/index";
import "./gallery.css";


const Gallery = () => {
  const [isOpen, setIsOpen] = useState({});

    const toggleOpen = (index) => {
        setIsOpen(prevState => {...prevState ,[index]:!(!!prevState[index]) });
    };
    
  return (
    <div className="panels">
      {data.restaurants.map((restaurant, index) => (
        <div
          className={`panel panel${index} ${isOpen[index] ? "open open-active" : ""}`}
          onClick={()=>toggleOpen(index)}
        >
          <Panels
            key={restaurant.name + index}
            description={restaurant.description}
            name={restaurant.name}
            website={restaurant.website}
          />
        </div>
      ))}
    </div>
  );
};

export default Gallery;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Different options exist for top layers with flexible widths aside from using position: absolute

The only method I'm aware of to place a layer on top is by using position: absolute. https://i.sstatic.net/R4j8i.jpg (favoring top, disliking bottom) However, this approach often prevents dynamic scaling with the rest of the page. You can attempt ...

Issues with typescript compiler when using React-beautiful-dnd

I recently updated react and react-beautiful-dnd to the newest versions and now I am encountering many type errors in my code: {sortedDimensions.map((dimension: any, index: number) => ( <Draggable key={index} ...

"Stable header and footer paired with comprehensive menu navigation spanning the entire length of

I've exhausted all of my options. I've attempted numerous coding examples from various websites and tutorials, but I can't seem to get this to work no matter how hard I try. I'm completely frustrated and ready to give up on figuring it ...

Tips on displaying a navbar only when the user starts scrolling

I recently put together a navbar component using react/next.js, and I am looking to make it appear only when the user starts scrolling. If anyone has any insights or suggestions on how to achieve this, I would be really thankful! Below is the code snippe ...

What is the purpose of defining the initialState in Redux?

As per the Redux documentation, it is considered a best practice to establish an initialState for your reducer. However, maintaining this initialState can become challenging when the state relies on data from an API response, leading to discrepancies betwe ...

When attempting to duplicate a project from Bitbucket and working in VS Code, I encountered several errors and warnings while running npm install

I have a project on Bitbucket that I'm trying to clone. The project is quite old, about 3 years old, so some packages may be outdated. However, when I run npm install, I am seeing a lot of warnings and errors. Additionally, the project was originally ...

Issue with deactivating the setting and focusing within a single function

I am currently working on creating edit form fields where a button needs to be clicked before the form field can be edited. However, I am facing challenges with toggling the disabled property and setting the focus of the element. Below is an example code s ...

What is the best way to transfer state information from a hook to be displayed in the App component in React

Is there a way to transfer the state(data) of info to the App hook, in order to showcase the properties within div elements? The function setInfo(info) saves the data intended for display on the Map hook and inspecting console.log(info) within _onClick rev ...

Is there a way to align input fields alongside the center of their corresponding labels?

Let me illustrate the issue I am encountering: https://jsfiddle.net/v10un11s/1/ Here is the snippet of my HTML code: <div> <div class="component"> <div> <label for="test1" id="short-label">Short label: </label&g ...

The dynamic links in Knockout.js are unresponsive to clicks

I've been working on a new project that utilizes knockout js. The main issue I'm facing is with setting up a table to display images and information from a form, being stored in an observable array. Each image is wrapped in an anchor tag, and the ...

Collapse the hamburger menu upon clicking on a link in the mobile menu

Whenever I click on a menu item, the page loads but the menu remains open. This JSX code represents the Mobile Menu: const MobileMenu = () => { const navigation = [ { link: '/applications', text: 'Applications' }, { link ...

Discovering the secrets of monitoring changes in children's length in React

Here is the code I am working with: const container = useRef(); const [items, setItems] = useState(); useEffect(()=>{ setItems(container.current.children.length); },[container.current, container.current.children.length]) return( <div ref={contain ...

When hovering over an image, another image is revealed

<div> <a href="#"><img src="images/Informasjon_button.png" width="120px" height="120px" /></a> </div> <div> <a href="#"><img src="images/Mail_button.png" width="120px" height="120px" /></a> </div ...

Leveraging nginx for serving dynamic content

I recently utilized nginx to host my node.js application. After creating a build of the app, I configured the root directory in my nginx.conf file to point to the location of the build folder. It was successful, and my application ran smoothly on nginx. H ...

Display a loading splash screen prior to loading Next.js

I am working on a NextJS website and I'm looking to incorporate a Splash Screen that displays before the site is fully loaded. However, since the Splash Screen is included in the NextJS code, it ends up loading after NextJS has rendered on the server ...

Guide on adjusting the size of an image based on either its width or height dimensions

Currently, I am retrieving product images from an API but unfortunately, they do not have consistent dimensions. My goal is to display these images within a 250x250 div. In some cases, the image is in portrait orientation and should be scaled based on its ...

When using classList.replace, it should swap out every instance of the class xxx1yyy with xx

I attempted to swap a class and came across this helpful example here: javascript: replace classList that is inside a conditional Unfortunately, my attempt at modification (shown below) did not work. The use of classList.replace should change all instanc ...

The abundance of information presented in the "object" type, specifically "[object Object]," prevents serialization as JSON. It is advised to exclusively provide data types that are JSON

Utilizing NextJS, I initially made internal calls to a /api route using fetch(). However, for production, it was evident that internal api calls within getServerSideProps are not allowed. Consequently, I am attempting to directly access my MongoDB database ...

Display the element once the class enters the viewport

I am attempting to display a div only when certain elements with a specific class are visible in the viewport. I made progress with this example: http://jsfiddle.net/blowsie/M2RzU/ $(document).ready(function(){ $('.myclass').bind('inv ...

React issue with no unused expressions

Currently, I am in the process of developing my own eCommerce platform using React. One crucial component of this project is the ProductList.js, which manages the display of various products through the code written in Product.js. To facilitate data manage ...