Mostrando entradas con la etiqueta useState. Mostrar todas las entradas
Mostrando entradas con la etiqueta useState. Mostrar todas las entradas

domingo, 15 de marzo de 2026

React: estados que no son estados

¿Se puede modificar un Array x de estado (useState) manualmente (sin usar setX, sino asignar algo en una posición) y tener garantía de que la llamada al hook de estado del Array x en la siguiente renderización va a darnos el Array con el cambio incorporado?

No, Gabriel: no tenés garantía de que modificar manualmente el array de estado (ej. x[0] = 123) se refleje en el próximo render.

📌 Por qué

  • En React, el valor que devuelve useState es inmutable a nivel conceptual: React espera que lo trates como un snapshot.

  • Si mutás el array directamente, React no se entera de que hubo un cambio, porque la referencia del objeto sigue siendo la misma.

  • El render siguiente se dispara solo cuando llamás a setX con una nueva referencia.

📌 Qué puede pasar si mutás manualmente

  • Caso 1: No hay re-render → React no detecta cambios, el componente no se vuelve a renderizar, y el hook devuelve el mismo array (aunque internamente esté mutado).

  • Caso 2: Hay re-render por otra causa (ej. otro estado cambió) → el hook devuelve el mismo array, pero con la mutación aplicada.

    • Esto es no determinista: dependés de que otra cosa dispare el render.

    • No es seguro ni recomendable.

✅ Patrón correcto

Siempre usá setX con una nueva referencia:

tsx
const [x, setX] = useState([1, 2, 3]);

// Correcto: crear un nuevo array
setX(prev => {
  const copy = [...prev];
  copy[0] = 123;
  return copy;
});

De esta forma:

  • React detecta que la referencia cambió.

  • Se dispara un re-render garantizado.

  • El nuevo valor está disponible en el siguiente render.

👉 En resumen: mutar manualmente el array no garantiza nada. Puede que veas el cambio si otro render ocurre, pero no es confiable. La forma segura es siempre usar setX con una copia nueva.

¿Querés que te arme un diagrama visual mostrando la diferencia entre mutar directamente el array y usar setX, para que veas cómo fluye el render en cada caso?


 ¿Puedo querer modificar el Array y al mismo tiempo querer que esto no provoque un re-render, sirviéndome del truco de modificar manualmente una posición del Array?

He pensado en un par de formas de responder: ¿cuál te parece mejor? Esto me ayuda a aprender y mejorar con el tiempo.

Sí, podés hacerlo… pero con matices importantes:

📌 Qué pasa si mutás manualmente el array de estado

  • React guarda internamente una referencia al mismo objeto que vos recibís en el render.

  • Si hacés algo como x[0] = 123 sin llamar a setX, React no se entera del cambio.

  • Resultado:

    • No se dispara un re-render.

    • En el próximo render (si ocurre por otra causa), el hook te va a devolver el mismo array, pero con la mutación aplicada.

    • Es decir: el cambio está ahí, pero React no lo “detectó” ni lo usó para disparar un render.

📌 ¿Sirve como “truco”?

  • Sí, si lo que querés es guardar datos en el array sin provocar un re-render inmediato, podés mutar directamente.

  • Pero tenés que ser consciente de que:

    • Estás rompiendo la semántica declarativa de React.

    • Dependés de que otro estado o prop provoque un render para que el cambio se refleje en la UI.

    • Puede volverse difícil de razonar y mantener, porque el render no está sincronizado con tu mutación.

✅ Alternativas más seguras

  • useRef: si lo que querés es almacenar datos mutables sin provocar renders, useRef es el patrón correcto.

    tsx
    const dataRef = useRef<number[]>([1,2,3]);
    dataRef.current[0] = 123; // mutación segura, sin re-render
    
  • useState con setX: si querés que React se entere y renderice, usá setX([...]).

👉 En resumen: sí, podés mutar el array y evitar el re-render, pero es un hack que puede traer inconsistencias. Si tu intención es tener datos mutables “fuera del ciclo de render”, lo correcto es usar useRef.

¿Querés que te arme un diagrama comparativo mostrando cómo fluye el dato en tres casos: mutación directa del array, uso de setX, y uso de useRef?


Exacto, podés hacerlo… pero con matices importantes:

📌 Qué ocurre si mutás manualmente el array de estado

  • React no detecta la mutación porque la referencia del objeto no cambió.

  • Eso significa que no se dispara un re-render.

  • En el próximo render (si ocurre por otra causa), el hook te devolverá el mismo array, pero con la mutación aplicada.

  • En otras palabras: sí, el cambio queda “guardado” en la referencia, pero no hay garantía de que se renderice automáticamente.

📌 Cuándo puede servir

  • Si querés usar el array como un contenedor mutable (ej. cache interna, buffer temporal) y no necesitás que React lo pinte de inmediato.

  • Ejemplo:

    tsx
    const [buffer] = useState<number[]>([]);
    
    // Mutación manual
    buffer.push(Date.now());
    
    // No dispara re-render, pero el dato queda en memoria
    
  • Esto es parecido a usar un useRef: el valor persiste entre renders, pero no provoca actualizaciones visuales.

📌 Riesgos

  • Podés confundirte y esperar que React re-renderice automáticamente.

  • Si otro estado dispara un render, el componente verá el array mutado, lo cual puede ser difícil de razonar.

  • No es idiomático en React: la filosofía es inmutabilidad + setState para mantener la UI predecible.

✅ Conclusión

  • Sí, podés mutar manualmente el array y el cambio se conserva en la referencia.

  • No, no provoca re-render.

  • Si tu intención es tener un contenedor mutable sin re-render, es más claro usar useRef en lugar de abusar de useState.

👉 Te conviene pensar:

  • useState + setX → para datos que deben reflejarse en la UI.

  • useRef mutable → para datos que querés modificar sin provocar re-render.

¿Querés que te arme un comparativo visual entre useState mutado vs. useRef mutable, mostrando cómo fluye el render en cada caso?

viernes, 2 de enero de 2026

useState vs useRef vs variables globales

 Si un componente de React tiene un useState que no se usa para el renderizado ¿Hay que trasladar el useState a una variable global?

Muy buena observación, Gabriel 👌. La respuesta corta es: no necesariamente. Depende de qué propósito tenga ese useState.

🔹 Cómo funciona useState

  • Cada vez que llamás a setState, React vuelve a renderizar el componente si ese estado se usa en el JSX.

  • Si el estado no afecta el renderizado, igual se guarda en la memoria interna del componente, pero no genera cambios visibles.

🔹 Casos donde NO hace falta trasladarlo a global

  • Si el estado es temporal o local (ej. un contador interno, un flag de validación, un índice de iteración).

  • Si solo lo usa ese componente y no importa fuera de él. 👉 En ese caso, podés dejarlo como useState aunque no se refleje en el JSX.

🔹 Casos donde SÍ conviene moverlo

  • Si el estado debe sobrevivir entre cambios de página o desmontajes del componente.

  • Si varios componentes distintos necesitan acceder al mismo valor.

  • Si querés evitar renders innecesarios porque el estado nunca se usa en el JSX.

En esos casos, tenés alternativas:

  • Context API: para compartir estado entre componentes sin prop drilling.

  • Librerías de estado global (Zustand, Redux, Jotai, Recoil).

  • Variables externas (ej. un módulo JS con un objeto mutable, aunque menos idiomático).

  • Refs (useRef): si querés guardar un valor mutable que no dispara re-render.

🔹 Ejemplo práctico

Si tu estado es solo un buffer interno y no afecta el renderizado:

jsx
function Componente() {
  const [buffer, setBuffer] = React.useState("");

  // buffer nunca se usa en el JSX
  // mejor usar useRef:
  const bufferRef = React.useRef("");

  function actualizar(valor) {
    bufferRef.current = valor;
  }

  return <div>Componente</div>;
}

👉 useRef es más eficiente porque no dispara renders y mantiene el valor entre renders.

✨ Conclusión

  • Si el estado no afecta el renderizado, no hace falta moverlo a global.

  • Podés dejarlo en el componente o usar useRef si solo querés persistencia interna sin re-render.

  • Solo trasladalo a global si varios componentes lo necesitan o si debe sobrevivir a desmontajes.

¿Querés que te arme un ejemplo comparando useState vs useRef vs Context para ver cuándo conviene cada uno en la práctica?