Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

111
Vistas
¿Es una práctica común en React mantener el mismo valor en estado y referencia?

Mi aplicación React usa setTimeout() y setInterval() . Dentro de ellos, necesito acceder al valor del estado. Como sabemos, los cierres están vinculados a su contexto una vez creados, por lo que usar valores de estado en setTimeout() / setInterval() no usará el valor más nuevo.

Simplifiquemos las cosas y digamos que mi componente se define como tal:

 import { useState, useEffect, useRef } from 'react'; const Foo = () => { const [number, setNumber] = useState(0); const numberRef = useRef(number); // Is this common? Any pitfalls? Can it be done better? numberRef.current = number; useEffect( () => setInterval( () => { if (numberRef.current % 2 === 0) { console.log('Yay!'); } }, 1000 ), [] ); return ( <> <button type="button" onClick={() => setNumber(n => n + 1)}> Add one </button> <div>Number: {number}</div> </> ); };

En total se me ocurrieron 3 ideas de cómo lograr esto, ¿alguna de ellas es un patrón reconocido?

  1. Asignando valor de estado a ref en cada renderizado, como arriba:

     numberRef.current = number;

    El beneficio es un código muy simplista.

  2. Usando useEffect() para registrar cambios de number :

     useEffect( () => numberRef.current = number, [number] );

    Este parece más React-ish, pero ¿es realmente necesario? ¿No degrada realmente el rendimiento cuando se puede usar una asignación simple del punto n.º 1?

  3. Usando un setter personalizado:

     const [number, setNumberState] = useState(0); const numberRef = useRef(number); const setNumber = value => { setNumberState(value); numberRef.current = value; };

¿Tener el mismo valor en el estado y la referencia es un patrón común con React? ¿Y alguna de estas 3 formas es más popular que otras por alguna razón? ¿Cuáles son las alternativas?

about 4 years ago · Juan Pablo Isaza
2 Respuestas
Responde la pregunta

0

2021-10-17 EDITAR:

Dado que esto parece un escenario común, quería envolver toda esta lógica en un intuitivo

 useInterval( () => console.log(`latest number value is: ${number}`), 1000 )

donde el parámetro useInterval siempre puede "acceder" al último estado.

Después de jugar un poco en CodeSandbox , me di cuenta de que no hay forma de que alguien más no haya pensado en una solución para esto.

He aquí, el hombre mismo, Dan Abramov, tiene una publicación de blog con una solución precisa para nuestra pregunta https://overreacted.io/making-setinterval-declarative-with-react-hooks/

Recomiendo encarecidamente leer el blog completo, ya que describe un problema general con la falta de coincidencia entre la programación React declarativa y las API imperativas. Dan también explica su proceso (paso a paso) de desarrollar una solución completa con la capacidad de cambiar el retraso del intervalo cuando sea necesario.

Aquí (CodeSandbox) puedes probarlo en tu caso particular.


Respuesta ORIGINALES:

1.

 numberRef.current = number;

Evitaría esto ya que generalmente queremos hacer actualizaciones de estado/ref en useEffect en lugar del método render.

En este caso particular, no tiene mucho impacto, sin embargo, si agregara otro estado y lo modificara -> se desencadenaría un ciclo de renderizado -> este código también se ejecutaría y asignaría un valor sin motivo (valor numérico no cambiaría).

2.

 useEffect( () => numberRef.current = number, [number] );

En mi humilde opinión, esta es la mejor manera de salir de las 3 formas que proporcionaste. Esta es una forma limpia/declarativa de "sincronizar" el estado administrado con el objeto ref mutable.

3.

 const [number, setNumberState] = useState(0); const numberRef = useRef(number); const setNumber = value => { setNumberState(value); numberRef.current = value; };

En mi opinión, esto no es lo ideal. Otros desarrolladores están acostumbrados a React API y es posible que no vean su configurador personalizado y, en su lugar, usen un setNumberState predeterminado al agregar más lógica esperando que se use como una "fuente de la verdad" -> setInterval no obtendrá los datos más recientes.

about 4 years ago · Juan Pablo Isaza Denunciar

0

Simplemente se ha olvidado de borrar el intervalo. Tienes que borrar el intervalo de renderizado.

 useEffect(() => { const id = setInterval(() => { if (numberRef.current % 2 === 0) { console.log("Yay!"); } }, 1000); return () => clearInterval(id); }, []);

Si no borra, esto seguirá creando un nuevo setInterval con cada clic. Eso puede conducir a un comportamiento no deseado.

Código simplificado:

 const Foo = () => { const [number, setNumber] = useState(0); useEffect(() => { const id = setInterval(() => { if (number % 2 === 0) { console.log("Yay!"); } }, 1000); return () => clearInterval(id); }, [number]); return ( <div> <button type="button" onClick={() => setNumber(number + 1)}> Add one </button> <div>Number: {number}</div> </div> ); };
about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda