when I click on the button all accordion elements are opened. how to make only clicked element to be opened. this is a react accordion app. I am not able to find the problem in the code.
import React, { useState } from "react";
//import {questions} from './api';
const questions = [
{
id: 1,
question: "what is a",
answer: "a is a"
},
{
id: 2,
question: "what is b",
answer: "b is b"
},
{
id: 3,
question: "what is c",
answer: "c is c"
}
];
function Accordian() {
const [toggle, settoggle] = useState(false);
function mapfunc(currentValue) {
return (
<div key={currentValue.id} className="elements">
<h3 className="question">
{currentValue.question}
<button
onClick={function () {
settoggle(!toggle);
}}
className="button"
>
{toggle ? "➖" : "➕"}
</button>
</h3>
{toggle && <p className="answer"> {currentValue.answer} </p>}
</div>
);
}
return (
<div>
<h1>Accordian App</h1>
{questions.map(mapfunc)}
</div>
);
}
export default Accordian;
CodePudding user response:
You need to move the toggle item with its logic to a separate component.
Item
import React, { useState } from "react";
const Item = ({ currentValue }) => {
const [toggle, settoggle] = useState(false);
return (
<div key={currentValue.id} className="elements">
<h3 className="question">
{currentValue.question}
<button
onClick={function () {
settoggle(!toggle);
}}
className="button"
>
{toggle ? "➖" : "➕"}
</button>
</h3>
{toggle && <p className="answer"> {currentValue.answer} </p>}
</div>
);
};
Accordian
const questions = [
{
id: 1,
question: "what is a",
answer: "a is a"
},
{
id: 2,
question: "what is b",
answer: "b is b"
},
{
id: 3,
question: "what is c",
answer: "c is c"
}
];
function Accordian() {
return (
<div>
<h1>Accordian App</h1>
{questions.map((item) => (
<Item currentValue={item} />
))}
</div>
);
}
export default Accordian;
CodePudding user response:
The problem here, is that the state is at the Accordion level. So if it is true, all of the children of the Accordion will be opened.
Instead, you should create a children component, that take as argument a question, and that has a local toggle state.
You could instantiate it like this for instance:
return (
<div>
<h1>Accordian App</h1>
{questions.map(question => <AccordionChildren question={question} />)}
</div>
)
