Reusable Collapsible Component with ReactJS
Tags: react
Published: 2021-07-09 10:35:04

Welcome, here's a guide teaching you how to create a simple and useful Reusable Collapsible Component, with ReactJS.

*Observation: I created this post considering that you know the basics of ReactJS. If you see anything wrong, please tell me!*

You can see it working at CodePen: [https://codepen.io/huferr/pen/NWjNLMy](https://codepen.io/huferr/pen/NWjNLMy)

Let's start by creating a functional component and call it `Collapsible`. It will return some HTML elements, which will structure our layout.

For this case, let's set:

- A `div` element, which will keep all the elements bellow;
- A `button` element, responsible for toggling the content visibility;
- A `div` element, which will handle our content.

Now, to make this component **reusable**, we have to pass some properties to it, to make this component accept data from outside, not having to change its structure every time. 

For this we'll set the *props: children* and *label*, by doing *props destructuring*, it means you don't have to call "props.children" or "props.label" every time you want to use these props. You only have to pass the prop names inside a curly brackets in the function.

Let's see what we've done so far:

```react
import React from "react";
import "./styles.css";

const Collapsible = ({ children, label }) => {
  return (
    <div className="container">
      <button className='toggle'>{label}</button>

      <div>{children}</div>
    </div>
  );
};

export default Collapsible;
```

OK, we have our button, that will make the content appear and disappear and we have our div with that content.

First thing, to make the content toggle, we'll need to set a CSS class (.show) to style how it's going to appear on our screen, and an other class (.content) to make it disappear:

```css
.content {
    width: auto;
    height: auto;
    margin-top: 10px;
    border: 1px solid #686868;
    display: none;
    justify-content: center;
    border-radius: 10px;
}

.show {
    display: flex;
}
```

As you can see, the magic is on the `display` property. When the div has the `.show` class, the content will be displayed!

Now, to make the toggle effect when click on the button, let's use the useState Hook! With this, let's set isOpen and setIsOpen, initializing with `false`.

*Obs.: Do it in the same Collapsible component.*

```react
import React, {useState} from 'react'
import './styles.css'

const Collapsible = ({children, label}) => {
    
    const [isOpen, setIsOpen] = useState(false)
```

Good! Now, with the `onClick` event in the button, let's pass a simple arrow function, setting the `isOpen` true or false, according to its previous state (if `isOpen === false`, set to `true` and vice-versa), using **!**, the logical "not" operator in javascript. See it:

```react
<button className='toggle' onClick={() => setIsOpen(!isOpen)}>{label}</button>
```

After that, to bind this event with the content, let's use a ternary operator in the content div class. So, isOpen === true ? use 'content and show' classes (content appears), isOpen === false ? use only 'content' (content disappears). See it:

```react
<div className={isOpen ? 'content show' : 'content'}>{children}</div>
```

Now, we have a **Reusable Collapsible Component**! You can change the label and children (content) prop, where the component will stay:

###Example 1###
```react
      <Collapsible label='Click Here'>
        <ul>
          <li>Profile</li>
          <li>Dashboard</li>
          <li>Logout</li>
        </ul>
      </Collapsible>
```
###Example 2###
```react
     <Collapsible label='Animals'>
        <ul>
          <li>Cat</li>
          <li>Dog</li>
          <li>Cow</li>
        </ul>
      </Collapsible>
```
###Results###

![Results](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dkqpwk9djozlnamheu1o.png)

*OTHER OBSERVATION: The purpose of this post was to show the functionality, so, sorry for the bad styling haha!*

Done! Thanks for reading this content, I hope it helps you in some way and, if you notice something wrong, feel free to help me leaving a comment bellow or find me on [twitter](https://twitter.com/thehuferr) !

You can also find me at:

[Github](https://github.com/huferr)
[Linkedin](https://www.linkedin.com/in/hugo-ferreira-it/)