Minimize all expanded containers in React

Although I've come across similar questions, none of them have addressed mine directly.

I managed to create a collapsible div component that expands itself upon click. However, I am looking for a way to make it so that when one div is expanded, all other expanded components will collapse.

The parent component where the collapsible component is included:

import React from 'react';
import { Collapsible } from '../../components';

const Parent = () => {
  return (
    <div>
      <Collapsible label="First label">
        <p>Children</p>
      </Collapsible>

      <Collapsible label="Second label">
        <p>Children</p>
      </Collapsible>

      <Collapsible label="Third label">
        <p>Children</p>
      </Collapsible>
    </div>
  );
};

export default Parent;

The Collapsible component:

import React, { Component } from 'react';

class Collapsible extends Component {
  constructor(props) {
    super(props);

    this.state = {
      opened: false,
    };

    this.openCollapsible = this.openCollapsible.bind(this);

  }

  openCollapsible() {
    this.setState(prevState => ({
      opened: !prevState.opened,
    }));
  }

  render() {

  const { label, children } = this.props;
  const { opened } = this.state;

  return (
    <div>
      <h2 onClick={this.openCollapsible}>
        {label}
      </h2>
      {opened ? <div>{children}</div> : null}
    </div>
  );
 }
}

export default Collapsible;

Overall, everything seems to be working fine. I just need help figuring out how to collapse all other collapsible components when one is expanded. Any assistance or guidance would be highly appreciated, even if it's just pointing me in the right direction for further research.

Sandbox: https://codesandbox.io/s/collapsible-component-tnhtn

Best regards!

Answer №1

To keep track of the open div's id/index within the parent div, you need to maintain it.

state = {openedId: null}

You can include an isOpen prop in each Collapsible component to compare its id with the openedId. When clicked, update the openedId in the parent component.

handleClick = (id) => {
   this.setState({openedId: id})
}

....


 <Collapsible 
    label="First label" 
    id={1}
    isOpen={id === openedId} 
    handleClick={this.handleClick}
 >
        <p>Children</p>
  </Collapsible>

Here is a helpful sandbox link

I recommend rendering the Collapsible elements using a config approach, where you create an array of objects like this:

const config = [
  {
    id: 1,
    label: 'First Label',
  },
  {
    id: 2,
    label: 'Second Label',
  },
];

....

config.map(({id, label} => <Collapsible label="Second label" id={2}>)

Answer №2

In my opinion, it can be beneficial to have a property within the state of your parent component like this:

class Parent extends Component {
  constructor(props) {
    super(props);

    this.state = {
     
      openedDiv: someBool
    };

  }

This approach will enable you to easily keep track of which div is currently "opened". You can then pass this information to the open div while passing your other value to the closed divs. Alternatively, you could utilize this property to monitor the "actual div" that is currently open.

Essentially, having something to maintain the state of the current opened div is essential!

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

Form fields do not pass validation when accessed via mobile devices

ISSUE: Successful form validation and async requests on desktop, but not functioning properly on mobile devices. TECHNOLOGY USED: Implemented nextjs, formik, and yup for the solution. DESCRIPTION: Developed a user-friendly form submission site that oper ...

JavaScript: Modifying an Array of Matrices

Could anyone assist me with updating a matrix array? I have an initial matrix with preset values and need to update specific coordinates within it. Here is the base matrix: var myMatrix = [ ['-','-','-','-',&ap ...

Creating a list repeater using v-for in Vue.js 2 with computed property

Seeking assistance with adding computed columns to a table (last three columns). Suspecting the issue lies in the computed property not correctly referencing the record. Any simple solutions that I might be overlooking? Appreciate any thoughts or insights! ...

Testing the signin component using jest and react testing library: A step-by-step guide

Struggling with creating an integrated test for a sign-in component. The main goal is to confirm that upon entering email and password credentials, and clicking submit, the user gets redirected to a specific page. Attempting to use waitForComponentToBeRemo ...

Unlock the Power of Core 2 MVC with the Cutting-edge Integration of

Looking for a solution on how to effectively use JQuery Datatables with Core MVC? Check out this helpful resource: Using jQuery DataTables Grid With ASP.NET CORE MVC I recently downloaded the sample project and made some modifications to fit my needs. It ...

CSS transformation: skewing without any blurring effects

Is there a way to create tilted drivers with borders and text without sacrificing the sharpness of the font and border? I have used the transform: skew(); CSS rule for tilting, but it has caused blurriness. How can I add font smoothing and maintain sharp b ...

Tips for incorporating unique styles to a component in ReactJS

Struggling to apply unique styles to a React Next.js component? Below is the code snippet for a button component: import styles from "./button.module.css"; const Button = props =>{ return( <div> <button className={styles.button}>{ ...

Prevent Mui popover from closing when clicking outside

Currently, I have implemented Mui Popover with ReactJS from the link here. One issue I am facing is that when a user clicks outside the popover, it automatically closes. Is there a way to disable this default behavior? Additionally, I would like to add a ...

Toggle class in Angular ngMessages based on validity, not just on error

As a beginner with ngMessages, I'm curious to know if there is a $valid counterpart for the $error object. In my exploration of the ngMessages documentation in Angular, I have only encountered discussions about the $error object. <form name="conta ...

Is there a way to eliminate the additional and varying pseudo-padding on text inputs in both Webkit and Gecko browsers?

The issue I'm facing is specific to input[type="text"] elements in Webkit. No matter what adjustments I make, it seems like there is an additional padding: 1px 0 0 1px (top and left only) applied to the element. A similar anomaly occurs in Gecko as w ...

Encountering npm issues while attempting to publish website on GitHub

Encountering errors in the terminal while attempting to deploy a website on Github using npm I am at a loss for what steps to take next PS C:\Users\user\modern_portfolio> npm run deploy > <a href="/cdn-cgi/l/email-protection" cl ...

What is the method for invoking a JSON web service with jQuery that necessitates basic authentication?

My knowledge of javascript is limited, but I am attempting to access a JSON web service that requires basic authentication using jQuery. Unfortunately, my searches on Google have not yielded any useful results. Can anyone tell me if what I am trying to a ...

What could be the reason for the Azure server sending a Bad Request response?

My NodeJS application is currently hosted on Azure server and all APIs are functioning correctly, providing the expected responses. The issue arises when trying to run a GET API like the following: https://demoapp.azurewebsites.net/mymenu?userId=piyush.d ...

Is there a way to identify when a radio button's value has changed without having to submit the form again?

Within this form, I have 2 radio buttons: <form action='' method='post' onsubmit='return checkForm(this, event)'> <input type = 'radio' name='allow' value='allow' checked>Allow ...

What is the method to store anchor text in a Session variable?

I'm currently working on a project where I've linked multiple pdf files in the master page. When clicking the anchor, the page redirects to the specified location and displays the pdf in an iframe. Now, I want the text within the anchor tag to be ...

Extract the data that was returned from the AJAX post function

I am looking to create a condition that is dependent on the data received from an ajax post outside of the post function function post(){ $.post('page.php',$('#form').serialize(), function(data) { if(data !== 'good'){a ...

Using Jest and React: How can I invoke a function within the expect(setInterval).toHaveBeenLastCalledWith() method?

While testing the component in the Jest environment, I am facing a challenge with passing the function callback inside the setInterval method. Every time I run the test, I encounter an error message related to the 'expect' statement: The mock ...

Preserving scroll position during page navigation in Next.js

Currently, I am working on a website using the Next.js boilerplate. Here is the routing code that I am using: import Link from 'next/link' <Link href={{ pathname: '/some-url', query: { param: something } }}> <div> ...

Instantly summing up two numbers with javascript

In my web development work using Visual Studio 2008, I encountered an interesting challenge. On a webpage, I have three textboxes labeled "Price," "Quantity," and "Amount." The task at hand is to calculate the value of "Amount" by multiplying the values ...

Creating a PDF document using HTML code

I am interested in creating a PDF file from an HTML code that includes the stylesheet rules using PHP. Currently, I am attempting to achieve this with the MPDF library. However, the generated PDF does not resemble the original HTML page. Many elements app ...