Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

199
Views
¿Por qué la configuración del estado en componentDidMount requiere que setTimeout funcione?

Tengo un componente que se parece al siguiente (sí, sé que existen ganchos React...). También he creado un ejemplo de CodeSandbox .

 export class App extends React.Component { state = { loadingStatus: "idle" }; componentDidMount() { debugger; setTimeout(() => { this.setState({ loadingStatus: "loading" }); }, 1); setInterval(() => { const loadingStatus = this.state.loadingStatus === "loading" ? "complete" : "loading"; this.setState({ loadingStatus }); }, 3000); } render() { const { loadingStatus } = this.state; return ( <div> <div>loadingStatus: {this.state.loadingStatus}</div> <div role="status"> {loadingStatus === "loading" && ( <img alt="loading" src="https://upload.wikimedia.org/wikipedia/commons/b/b1/Loading_icon.gif?20151024034921" /> )} {loadingStatus === "complete" && ( <span className="visually-hidden">Loading has completed</span> )} </div> {loadingStatus === "complete" && ( <div>Content has loaded. The page will reload again momentarily.</div> )} </div> ); } }

Este componente demuestra cómo crear un indicador de carga de página que sea accesible para los usuarios de lectores de pantalla. La clave es el uso de un elemento con role="status" que anunciará cuando cambie su contenido. Necesita contener:

  • nada inicialmente para que, cuando sí tenga contenido, se anuncie el nuevo contenido.
  • el indicador de carga cuando el componente está en estado de carga, lo que debería ocurrir inmediatamente después de que se monte el componente.
  • un elemento visualmente oculto después de que se complete la carga que anunciará a los usuarios de lectores de pantalla que la carga se completó.

El problema que tengo es que cuando cambio el estado de carga de "inactivo" a "cargando" en el componente DidMount, no se "registra" en el DOM a menos que lo ajuste en un setTimeout (), incluso solo 1 ms demora. Si no tengo setTimeout(), no se anuncia el cambio de contenido en mi elemento role="status" .

Lo interesante es que, si elimina setTimeout() y abre las herramientas de desarrollo en el navegador, el debugger; se rompe y puede ver que la interfaz de usuario se representa cuando el estado es "inactivo". Esto me tiene confundido por qué es necesario un retraso.

Para ser claros, el problema es que, sin setTimeout(), el anuncio inicial de "carga" no ocurre. Necesitará un lector de pantalla (por ejemplo, NVDA) para probar.

Gracias por adelantado.

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

Se llama al método componentDidMount después de que se haya renderizado el componente. Es por eso que puede verlo cuando agrega la declaración del depurador.

Llamar setState dentro de componentDidMount activará una segunda llamada para render . Que lee el nuevo estado y actualiza el DOM.

No estoy seguro de por qué estaba usando setInterval pero si simplifica su ejemplo, en realidad funciona de la manera que esperaría.

 componentDidMount() { this.setState({ loadingStatus: 'loading' }); setTimeout(() => { this.setState({ loadingStatus: 'complete' }); }, 3000); }

Lo que provoca el siguiente flujo:

  • estado = { estado de carga: 'inactivo' }
  • prestar
  • componenteDidMount
  • setState({ estado de carga: 'cargando' })
  • prestar
  • 3 segundos después... setState({ loadingStatus: 'complete' })
  • prestar

En el ejemplo anterior setTimeout(..., 3000) representa una llamada API simulada. Lo más probable es que desee realizar una operación asincrónica como esta:

 componentDidMount() { this.setState({ loadingStatus: 'loading' }); fetch('/your/api/endpoint').then(response => { // do something with the response this.setState({ loadingStatus: 'complete' }); }); }

Si aún tiene problemas con él después de probar el método anterior, podría deberse a que setState es asíncrono y los cambios que realice se pueden procesar por lotes si ocurren en un flujo de ejecución continuo. Envolver su código en una devolución de llamada de requestAnimationFrame garantizará que el renderizado anterior esté completo antes de actualizar el estado.

 componentDidMount() { requestAnimationFrame(() => { this.setState({ loadingStatus: 'loading' }); fetch('/your/api/endpoint').then(response => { // do something with the response this.setState({ loadingStatus: 'complete' }); }); }); }
about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!