Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

77
Visualizações
FAQ's section individual toggle incorrectly opening all parts on click

I've been trying to do a sort of toggle whereby you are able to click on a question to expand the answer. I've tried adapting the code from https://codesandbox.io/s/polished-rain-xnez0?file=/src/App.js, which was from another question on here.

Instead of creating a map in the parent component and passing in them separately to a reusable 'Expandable' component to render separate functional components as shown in the example, I tried creating the map within the FAQ component:

FAQ Expandable Component:

const FAQ = ({ questions }) => {

const [expanded, setExpanded] = useState(false);

const handleClick = () => {
    setExpanded((prevExpanded) => !prevExpanded);
  };

const renderedQuestions = questions.map((question, index) => {

    return (
        <React.Fragment key={question.id}>
            <FAQIndividualWrapper>
                <FAQTitle 
                    className='title'
                    onClick={() => handleClick()}
                >
                    {/* <i></i> */}
                    {question.title}
                </FAQTitle>
                <FAQContent className='content' style={{ display: expanded ? "block" : "none" }}>
                    {question.content}
                </FAQContent>
            </FAQIndividualWrapper>
        </React.Fragment>
    )
})


return (
    <>
    {renderedQuestions}
    </>
)

Parent Component:

const questions = [
{
    id: 1,
    title: 'Question 1',
    content: 'Answer 1'
},
{
    id: 2,
    title: 'Question 2',
    content: 'Answer 2'
}
]

const FAQSection = () => {
    return (
        <FAQPageContainer>
            <FAQWrapper>
                <FAQ questions={questions} />
            </FAQWrapper>

        </FAQPageContainer>
    )
}

However, my code results in all the answers being expanded on any click of either question. Why is this happening?

Also, how should I structure and fix the code for 'ideal' programming?

Thank you!

about 4 years ago · Juan Pablo Isaza
2 Respostas
Responde à pergunta

0

The problem with your code is that you only have one expanded state for all questions. This means the open/collapse state is the same for all questions.

If you want to include all of your code inside one component. You need to somehow distinguish the open/collapse state of each child.

Here I'm using an array to store individual open/collapse state of each child.

  // initial state is an array with the length of your questions array, default to false
  const [expandedIndexes, setExpandedIndexes] = useState(
    Array(info.length).fill(false)
  );
 
  const handleClick = (index) => {
    setExpandedIndexes((prevExpandedIndexes) => {
      const newState = [...prevExpandedIndexes];
      // set state for the corresponding index
      newState.splice(index, 1, !prevExpandedIndexes[index]);
      return newState;
    });
  };
  return (
    <div className="details">
      {info.map(({ title, details, id }, index) => (
        <div key={id} className="details-wrapper">
          <div>
            <h3 className="title">{title}</h3>
            <button onClick={() => handleClick(index)}>+</button>
          </div>
          <p
            className="text"
            // check the corresponding state to display
            style={{ display: expandedIndexes[index] ? "block" : "none" }}
          >
            {details}
          </p>
        </div>
      ))}
    </div>
  );

Codesandbox

Also, how should I structure and fix the code for 'ideal' programming?

Ideally, you want to follow the convention in your codesandbox link above. That way you don't need to deal with this kind of logic, each child will have its own state/handleClick function.

about 4 years ago · Juan Pablo Isaza Relatório

0

It is correct that the issue is caused by the fact that you've only a single boolean state.

Use an object to store the ids of the questions that are expanded, toggling a boolean value for each.

Example:

const FAQ = ({ questions }) => {
  const [expanded, setExpanded] = useState({});

  // Curried callback to enclose the id in callback scope
  const handleClick = id => () => {
    setExpanded(expanded => ({
      ...expanded,
      [id]: !expanded[id],
    }));
  };

  return questions.map((question) => (
    <FAQIndividualWrapper key={question.id}>
      <FAQTitle
        className='title'
        onClick={handleClick(question.id)}
      >
        {question.title}
      </FAQTitle>
      <FAQContent
        className='content'
        style={{ display: expanded[question.id] ? "block" : "none" }}
      >
        {question.content}
      </FAQContent>
    </FAQIndividualWrapper>
  ));
}
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda