guys. I'm learning reactJS and I'm trying to make a nested accordion from scratch, but i can't figure out how to handle the sub-levels.
This is what I've built so far. I have a few questions.
- How can i handle the usaState hook so it can be used on the different levels of the accordion (as it is now, I'm using it to change the class "active" dynamically, but since all levels use the same hook, all open and close together).
- Is there a better way than multiple maps?
- How can i make this code more like a react component (reusable). I feel it is not the right way to build a component.
- Is it common to use those libraries (bootstrap react, semantic-ui-react, etc) professionally?
Thanks!
My data:
export default [
{
id: 1,
title: 'Smokes',
children: [
{
id: '1A',
title: 'CT',
children: [
{
id: '',
title: 'From half wall',
// children: [],
},
{
id: '',
title: 'From car',
// children: [],
},
{
id: '',
title: 'From ct Base',
// children: [],
},
],
},
{
id: '1B',
title: 'A long',
children: [
{
id: '',
title: 'From top mid',
// children: [],
},
{
id: '',
title: 'From 2nd mid',
// children: [],
},
],
},
],
},
{
id: 2,
title: 'Flashes',
children: [
{
id: '2A',
title: 'Pit',
children: [
{
id: '',
title: 'From t top mid',
// children: [],
},
{
id: '',
title: 'From 2nd mid',
// children: [],
},
{
id: '',
title: 'From apps',
// children: [],
},
],
},
{
id: '2B',
title: 'Bomb A',
children: [
{
id: '',
title: 'From banana',
// children: [],
},
],
},
],
},
{
id: 3,
title: 'Molotovs',
children: [
{
id: '3A',
title: 'Patio',
children: [
{
id: '',
title: 'From t top mid',
// children: [],
},
{
id: '',
title: 'From boiler',
// children: [],
},
],
},
{
id: '3B',
title: 'Back site A',
children: [
{
id: '',
title: 'From A long',
// children: [],
},
],
},
],
},
];
Accordion.js:
import React from 'react';
import { useState } from 'react';
import accordionData from '../../data/accordion';
function Accordion() {
const [selected, setselected] = useState('');
const toggle = () => {
setselected(selected === '' ? 'active' : '');
};
return (
<section className="accordion-section">
<div className=" flex-container accordion-wrapper">
<div className="accordion">
{accordionData.map((item) => (
<div className="accordion-items">
<div className="accordion-title" onClick={() => toggle()}>
<h2>{item.title}</h2>
{/* If seleceted render "-", otherwise "+" */}
<span>{selected === 'active' ? '-' : '+'}</span>
</div>
<div>
{item.children.map((stratItem) => (
<div>
<div
className={`accordion-item destination ${selected}`}
onClick={() => toggle()}
>
{stratItem.title}
</div>
<div>
{stratItem.children.map((originItem) => (
<div
className={`accordion-item origin ${selected}`}
onClick={() => toggle()}
>
{originItem.title}
</div>
))}
</div>
</div>
))}
</div>
</div>
))}
</div>
</div>
</section>
);
}
export default Accordion;
app.css:
.accordion-section {
background-color: #687980;
}
.accordion-wrapper{
background-color: #687980;
color: #F5F2E7;
height: 100%;
width: auto;
}
.accordion {
width: 25%;
height: auto;
padding: 15px;
}
.accordion-title {
display: flex;
justify-content: space-between;
align-items: center;
padding-left: 10px;
cursor: pointer;
background-color: #2C3333;
}
.accordion-title span {
font-size: 30px;
padding-right: 5px;
}
.accordion-items {
padding: 15px;
margin: 5px 0;
font-weight: lighter;
}
.accordion-item {
height: 30px;
display: flex;
align-items: center;
/* border: 1px solid #2C3333; */
margin: 2px;
cursor: pointer;
transition: 0.20s ease;
background-color: #4f4f53;
}
.accordion-item:hover{
transform: translate(5px, 5px);
transform: scale(5px);
background-color: #cfe3f3;
font-weight: bold;
color:#2C3333
}
.destination {
padding-left: 15px;
font-weight: 500;
font-size: 18px;
max-height: 0;
overflow: hidden;
transition: all 0.5s cubic-bezier(0,1,0,1);
}
.destination.active {
height: auto;
max-height: 999px;
transition: all 0.5s cubic-bezier(0,1,0,1);
}
.origin {
padding-left: 30px;
font-weight: 300;
max-height: 0;
overflow: hidden;
transition: all 0.5s cubic-bezier(0,1,0,1);
}
.origin.active {
height: auto;
max-height: 999;
transition: all 0.5s cubic-bezier(0,1,0,1);
}