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

196
Visualizações
addEventListener doesn't work on initial render

I'm trying to create simple accordion in React. If I open/refresh whole page, onclick event is not triggered when I click on buttons. It works properly only after I change something in code and component rerenders. No bugs in console and honestly I have no idea what is happening here. Thanks in advance

import { useEffect } from "react"

function FAQ () {
  const accordionBtn = document.querySelectorAll('.accordionTitle')
  const allTexts = document.querySelectorAll('.text')

  useEffect(() => {
    accordionBtn.forEach(function (el) {
      el?.addEventListener('click', toggleAccordion)
    })
  }, [])
 
  function toggleAccordion (el: Event) {
    
    const targetText = (el?.currentTarget as Element).nextElementSibling?.classList
    const target = (el?.currentTarget as Element).classList

    if (!(targetText?.contains('show'))) {
      accordionBtn.forEach(function (el) {
        el.classList.remove('accordionTitleActive')
        allTexts.forEach(function (el) {
          el.classList.remove('show')
        })
      })
      targetText?.add('show')
      target?.add('accordionTitleActive')
    }
  }

  return (
    <div>
      <ul className='accordion'>
        <li>
          <h2 className='accordionTitle'>Title1 </h2>
          <div className='text show'>
            Content1
          </div>
        </li>
        <li>
          <h2 className='accordionTitle'>Title2 </h2>
          <div className='text'>
            Content2
          </div>
        </li>
        <li>
          <h2 className='accordionTitle'>Title3 </h2>
          <div className='text'>
           Content3
          </div>
        </li>
      </ul>
    </div>
  )
}

export default FAQ
about 4 years ago · Juan Pablo Isaza
3 Respostas
Responde à pergunta

0

When you retrieve the DOM elements at that time, those elements are not even in DOM. If you move the querySelectorAll calls to useEffect it should solve your problem. Remember that useEffect callback is called after the component has been painted on the screen.

But as Andy mentioned in comment above it is strongly not recommended to access DOM directly. Even if you have to(which I don't think is required in your scenario) there is useRef

enter image description here

about 4 years ago · Juan Pablo Isaza Relatório

0

Here's how I might approach it. It uses state to maintain the number of the accordian, and then you can just adjust the class of the child elements accordingly.

const { useState } = React;

function Example() {

  // Use state to identify the accordian you want open
  const [ show, setShow ] = useState(0);

  // `handleClick` grabs the id from the accordian
  // and then sets the state
  function handleClick(e) {
    const { id } = e.target.parentNode.dataset;
    setShow(Number(id));
  }

  // Now, for each element check to see if the id matches
  // the state and show that text
  return (
    <div onClick={handleClick}>
      <div data-id="1">
        <h3>Accordian one</h3>
        <p className={show === 1 && "show"}>Accordian one text</p>
      </div>
      <div data-id="2">
        <h3>Accordian two</h3>
        <p className={show === 2 && "show"}>Accordian two text</p>
      </div>
      <div data-id="3">
        <h3>Accordian three</h3>
        <p className={show === 3 && "show"}>Accordian three text</p>
      </div>
    </div>
  );
};

// Render it
ReactDOM.render(
  <Example />,
  document.getElementById("react")
);
p { display: none; }
h3:hover { cursor: pointer; }
.show { display: block; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="react"></div>

about 4 years ago · Juan Pablo Isaza Relatório

0

I would suggest - Refactor your code to use class-based components. Not that the existing code is ugly, but you should use best practices when it comes to React and rendering html smoothly. Moreover, by doing so, you can also use React Component Lifecycle methods - which will be very handy!

A good article on class based components : Link

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