El gancho useState: una guía completa PlatoBlockchain Data Intelligence. Búsqueda vertical. Ai.

El gancho useState: una guía completa

¿Qué es un estado?

Antes de profundizar en el gancho useState, primero entendamos el término estado.

El estado representa información sobre algo en un momento dado.

Por ejemplo, consideremos un cuadro de texto.

Inicialmente, no hay nada dentro de este cuadro de texto, por lo que su estado es vacío. Suponga que comienza a escribir Hola dentro de él, por cada pulsación de tecla, el estado del cuadro de texto cambiará. Al principio será “H”, luego “Él”, luego “Hel” y así sucesivamente hasta convertirse en “Hola”.

Además, observe que a medida que escribe, no pierde el valor anterior. Si presiona "H" seguido de "e", obtendrá "Él" y no solo "e". En otras palabras, puedes pensar en el estado como el memoria del cuadro de texto.

La necesidad de estado en un componente React.

Entendamos esto con la ayuda de un ejemplo.

Codesanbox sin estado

Aquí tenemos un Contador de clics que muestra el número de veces que se hizo clic en el botón Incrementar.

Estamos usando un variable local “contador” para llevar la cuenta de los clics.

Cada vez que hacemos clic en el botón Incrementar, manejarHaga clic se invocará la función. Esta función aumentará el valor del contador en 1 y también registrará el valor en la consola.

Continúe, haga clic en el botón Incrementar en la vista previa de CodeSandbox.

¿No pasó nada?

Bueno, nuestra lógica parece ser correcta. El valor registrado en la consola (CodeSandbox) se actualiza correctamente cada vez que hacemos clic, pero ¿por qué esta actualización no se refleja en la interfaz de usuario?

Es por la forma en que funciona React.

  • Los cambios en las variables locales no activan una nueva representación.
  • Durante una nueva representación, se crea un componente desde cero, es decir, la función de un componente (en este ejemplo, es la función ClickCounter) se ejecuta una vez más. Dado que las variables (por ejemplo, contador) son locales a la función, sus valores anteriores se pierden.

Entonces, ¿cómo hacemos que el componente recuerde valores entre renderizaciones?

¡Si, lo tienes bien! Hacemos esto con la ayuda de la usoEstado gancho.

El gancho useState

El enlace useState proporciona mecanismos para conservar el estado y desencadenar una nueva representación.

Veamos su uso.

import React, { useState } from "react";
const state = useState(initialValue);

// OR

const state = React.useState(initialValue);

El gancho useState devuelve una matriz que contiene dos elementos:

  • A variable de estado que retiene sus valores durante las re-renderizaciones. El valor inicial pasado a useState se asigna a la variable de estado durante el primer procesamiento.
  • A función de colocador que actualiza la variable de estado y también desencadena una nueva representación.
const state = useState(0);
const data = state[0];
const setData = state[1];

Usar desestructuración de matrices , podemos refactorizar las declaraciones anteriores en una sola declaración, como se muestra a continuación:

const [data, setData] = useState(0);

El valor inicial pasado a useState se usa solo durante el primer renderizado. Para re-renderizados, se ignora.

Contador con useState

Ahora, actualicemos el ejemplo de contador anterior para incluir el enlace useState.

  • Dado que necesitamos el valor del contador entre renderizaciones, convirtámoslo en un estado.
const [counter, setCounter] = useState(0);
  • Llamar a setCounter dentro de la función handleClick.
const handleClick = () => {
  setCounter(counter + 1);
  console.log(`%c Counter:${counter}`, "color:green");
};

La función setCounter actualizará el valor del contador en 1 y activará una nueva representación. Cuando se llama a la función del componente para volver a renderizar, la variable de estado devuelta por useState tendrá el valor actualizado.

Pruebe CodeSandbox con el código actualizado. Haga clic en el botón Incrementar y vea la magia de useState en acción.

Codesanbox con useState

Puede verificar que en una nueva representación, el componente funcional Contador de clics se vuelve a llamar al ver los registros de la consola. El registro "Inicio de ClickCounter" que se agrega al comienzo del componente se registrará en cada renderizado.

primer render

volver a renderizar

Función de actualización

Supongamos que queremos aumentar el valor del contador en 4 en cada clic.

const handleClick = () => {
  setCounter(counter + 1);
    setCounter(counter + 1);
    setCounter(counter + 1);
    setCounter(counter + 1);
    console.log(`%c Counter:${counter}`, "color:green");
    };

Suponga que el valor inicial del contador es 0. ¿Qué espera ver una vez que se hace clic en el botón?

Sin función de actualización

Esperabas que el conteo fuera 4, ¿verdad? Pero, ¿por qué ves 1 en su lugar?

a) Cada render está asociado a un estado. El valor de ese estado permanece bloqueado durante la vida útil de ese renderizado.

Observe que el registro dentro de la función handleClick imprime el valor del contador como 0.

No importa cuántas veces llame al método setCounter, el valor de contador sigue siendo el mismo.

const handleClick = () => {
  setCounter(counter + 1);
    setCounter(counter + 1);
    setCounter(counter + 1);
    setCounter(counter + 1);
    console.log(`%c Counter:${counter}`, "color:green");
    };
b) Hasta que se ejecute todo el código dentro de un controlador de eventos, React no activará una nueva representación.

Por esta razón, cada llamada a setCounter no desencadena una representación individual. En cambio, React agrega estas funciones de establecimiento en una cola. Los ejecuta en el orden en que fueron puestos en cola. Las actualizaciones realizadas al estado después de ejecutar todas las declaraciones se reflejan en el siguiente renderizado. Esta puesta en cola de múltiples actualizaciones de estado se conoce como procesamiento por lotes. Permite que React sea más eficaz.

Por lo tanto, aquí obtenemos un solo renderizado en lugar de 4 renderizados diferentes.

Este ejemplo es simple y puede solucionar este problema actualizando el código como se muestra a continuación:

const handleClick = () => {
setCounter(counter + 4);
    console.log(`%c Counter:${counter}`, "color:green");
    };

Pero, ¿qué pasaría si tuviera un caso de uso en el que quisiera actualizar el estado varias veces antes del próximo renderizado?

Ahí es donde el _ actualizador La función _ es útil.

Podemos refactorizar el ejemplo anterior con la función de actualización de la siguiente manera:

const handleClick = () => {
  setCounter(prevCounter => prevCounter + 1);
    setCounter(prevCounter => prevCounter + 1);
    setCounter(prevCounter => prevCounter + 1);
    setCounter(prevCounter => prevCounter + 1);
    console.log(`%c Counter:${counter}`, "color:green");
    };

Aquí contador anterior ⇒ contador anterior + 1 representa la función de actualización.

Como se explicó anteriormente, estas instrucciones de actualización también se ponen en cola (por lotes).

La función de actualización recibe un estado pendiente/anterior que utiliza para calcular el siguiente estado.

Función de actualización por lotes

A continuación se muestra CodeSandbox con la función de actualización agregada. Intente hacer clic en el botón de incremento.

Sandbox de función de actualizador

Función de inicializador

Eche un vistazo al ejemplo a continuación. Aquí llamamos a la función getItems para obtener el valor inicial del estado.

import React from "react";
import { useState } from "react";
function ListItems() { 
  const getItems = () => { 
    console.log(`%c getItems called`, "color:hotpink");
    	return Array(50).fill(0); 
    }; 
  const [items, setItems] = useState(getItems()); 
    
    return ( 
    	<div className="card">
        <ul> {items.map((item, index) => 
        	( <li key={index}>Item {index + 1}		</li>))} 
        </ul> <button onClick={() => setItems([...items, 0])}>Add Item</button> 	</div> );
} 
export default ListItems;

Esta función crea una matriz con tamaño 50 y llena la matriz con ceros. Consulte la imagen a continuación.

Matriz llena de 50 ceros

Estos elementos se muestran en la pantalla.

Todo parece estar bien, pero tenemos un problema aquí.

Haga clic en el Añadir artículo (ubicado después de la lista de elementos) para agregar un nuevo elemento a la lista. Observa los registros.

Sin función de inicializador

¿Ves el problema aquí?

El registro "getItems called" se agrega a la consola cada vez que agrega un elemento. Esto significa que esta función se llama en cada renderizado.

Recuerde que useState ignora el valor inicial que se le pasó después del primer procesamiento, pero aquí el valor inicial todavía se está recalculando. Esto puede ser costoso si estamos creando matrices grandes o realizando cálculos pesados.

Podemos resolver este problema pasando obtener elementos como un _ inicializador _ función.

Ahora, hagamos un pequeño cambio en el código.

const [items, setItems] = useState(getItems);

Con función de inicializador

Vea la ventana de la consola en CodeSandbox. Tenga en cuenta que el registro "getItems called" solo se imprime en el primer renderizado. Cuando se agregan elementos posteriores, este registro no está allí.

Aunque no hay una diferencia visual entre los dos ejemplos, en términos de rendimiento son diferentes.

Recuerde que cuando necesite una función para el estado inicial, siempre pase la función o llame a la función dentro de otra función. Nunca llame a la función directamente.

✅ const [items, setItems] = useState(getItems);
✅ const [items, setItems] = useState(() => getItems());
❌ const [items, setItems] = useState(getItems());

¿Cuántos ganchos useState puedo tener?

Puede tener tantos ganchos useState dentro de un componente como requiera.

Ver CodeSandbox

Múltiples anzuelos useState

El siguiente componente tiene tres estados diferentes: nombre de usuario, contraseña, keepMeSignedIn.

Intente actualizar los valores de nombre de usuario, keepMeSignedIn. Los estados actualizados se registran en la consola cuando se hace clic en el botón de inicio de sesión.

Destacados

  • useState proporciona un mecanismo para desencadenar una nueva representación y mantener el estado entre las nuevas representaciones.
  • Utilice la función de actualización cuando necesite:
    • Calcular el siguiente estado basado en el estado anterior.
    • Realice varias actualizaciones del estado antes del siguiente renderizado.
  • Si el estado inicial se obtiene de una función, utilice la sintaxis de la función de inicialización.
  • Puede haber múltiples enlaces useState dentro de un componente.

¿Te gustó esta publicación? Compártalo con otros.
Escrito originalmente para mi blog personal: https://gauravsen.com/use-state-hook

Sello de tiempo:

Mas de Hecho de reacción de Codementor