There is a challenge on the frontend mentor website (FAQ accordion). I have solved the challenge using React. However, my code is not working properly.
Except for the first click on any question when page loads, I have to double-click each question to toggle it. I suspect something wrong in my code with useState.
I created a component that renders a list of questions/answers and displays them using the details
HTML tag. I want to solve the problem using the details tag only.
Here is my code for the component:
import { Fragment, useState } from "react";
import minus from "./icon-minus.svg";
import plus from "./icon-plus.svg";
const Faq = ({ questionsObj }) => {
const [isOpen, setIsOpen] = useState(false);
const [selectedId, setSelectedId] = useState(null);
function handleClick(id) {
if (selectedId !== id) {
setSelectedId(id);
}
if (selectedId === id) {
setIsOpen(!isOpen);
}
}
return (
<main>
{questionsObj.map((question, index) => (
<Fragment key={question.id}>
<details
onClick={(e) => handleClick(question.id)}
open={selectedId === question.id ? isOpen : null}
>
<summary>
<span>{question.question}</span>
<img
src={
isOpen === false && selectedId === question.id
? `${minus}`
: `${plus}`
}
alt=""
/>
</summary>
<p className="animate__animated animate__flipInX">
{question.answer}
</p>
</details>
{index !== questionsObj.length - 1 ? <hr /> : null}
</Fragment>
))}
</main>
);
};
export default Faq;
I also think my code is not good to solve simple problem like this accordion. I would appreciate if someone tell me where is the problem in my code.
Thanks
2
Answers
See issues/15486#issuecomment-873516817, you should use
e.preventDefault()
in the click event handler of<details/>
Besides, you don’t need the
isOpen
state. TheselectedId
state is enough.e.g.
stackblitz
useState
worksasync
, so when you click first timeisOpen
will be false because condition will match id(latest value) with selectedId(old value). so it will work on second click.Solution is As above ans you don’t need 2 diff state.
selectedId
is enough for you, but clear id on second click so it can close as like as your code.