I'm facing some issues with my React application.
First I will explain what I want in my app then I will talk about the issues.
I have a list of 6 Services and I want to wrap each service list in Accordion. Whenever the user clicks the " " button for the specific service I want that list to be displayed with slides down with a growing margin-bottom, depending on the number of items in the respective list without overlapping the below element.
While trying to achieve this, I'm facing the following issues.
1- when I click " " button it toggles all 6 services and their list items are getting displayed.
2- all list items overlapping the below elements.
I tried with useState()
const [showServices, setShowServices] = useState(false);
const toggle = () =>{
setShowServices((prevState) => !prevState);
}
<div className="services__service__description">
<h4 className="title">Services</h4>
<span style={{cursor: 'pointer', fontSize: '20px', fontWeight: 'bold'}} id='showBtn'
onClick={toggle}> </span>
<div className="accordion">
{text.map((t) => (
<div className="content" id='services'>
<div id='srvs' key={t.id}>
{showServices ? t.info : ''}
</div>
</div>
))}
</div>
</div>
CodePudding user response:
As I guss from part of your code, you binded single state to all Service related info.
The state showServices
is shared between all item and when it changed from one item, then affect all other items.
Define new child component for info like example that i prepare for you.
function ServiceDetail({ service }) {
const [show, setShow] = React.useState(false);
function toggle() {
setShow(s => !s);
}
return <div className="detail">
<h4 className="title">{service.name}</h4>
<span style={{ cursor: 'pointer', fontSize: '20px', fontWeight: 'bold' }} id='showBtn'
onClick={toggle}> </span>
<div className="accordion">
{service.detail.map((t, index) => (
<div key={index} className="content" id='services'>
<div id='srvs'>
{show ? t : ''}
</div>
</div>
))}
</div>
</div>
}
function Service() {
const [services, setServices] = React.useState(
[
{
id: 1,
name: "Service 1",
detail: ["list-1","list-2","list-3"]
},
{
id: 2,
name: "Service 2",
detail: ["bb"]
},
{
id: 3,
name: "Service 3",
detail: ["bb"]
},
{
id: 4,
name: "Service 4",
detail: ["bb"]
},
{
id: 5,
name: "Service 5",
detail: ["bb"]
}
]
);
return <div className="service">
{
services.map((service) => {
return <ServiceDetail key={service.id} service={service} />
})
}
</div>
}
function App() {
return <Service />;
}
ReactDOM.render(< App className="app" />, document.getElementById("root"));
.app{
width:100%;
}
.service{
display:grid;
column-gap: 1rem;
align-items:flex-start;
align-content:flex-start;
row-gap: 2rem;
grid-template-columns: 1fr 1fr 1fr;
}
.detail{
color:#9c772d;
background:#eeeeee;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Edit: For size problem, just you need to add following css to container as i add to sample:
align-items:flex-start;
align-content:flex-start;