React
Tutorial React: Estado local con useState y useReducer
React: Aprende a gestionar el estado local con useState y useReducer en este tutorial práctico. Mejora tus habilidades en componentes funcionales con React.
Aprende React GRATIS y certifícate¿Qué es el estado local?
El estado local en React se refiere a los datos que son manejados dentro de un componente y que afectan su comportamiento y renderizado. Este estado es privado al componente en el que se define, lo que significa que no es accesible directamente desde otros componentes. En React, el estado local se gestiona principalmente mediante los hooks useState
y useReducer
.
El estado local permite a los componentes de React mantener y actualizar datos sin necesidad de recurrir a un sistema de gestión de estado global. Esto es útil para componentes que manejan datos específicos y no necesitan compartir esa información con otros componentes.
Consideraciones sobre el estado local
El estado local es fundamental para crear componentes interactivos en React. Sin embargo, es importante tener en cuenta las siguientes consideraciones:
- Encapsulamiento: El estado local está encapsulado dentro del componente, lo que mejora la modularidad y la reutilización del código.
- Renderización: Cada vez que se actualiza el estado local, el componente se vuelve a renderizar, lo que puede afectar el rendimiento si no se maneja adecuadamente.
- Simplicidad: Para estados simples y componentes individuales,
useState
es generalmente suficiente. Para estados más complejos o cuando las actualizaciones dependen del estado anterior,useReducer
puede ser más apropiado.
¿Qué es useState?
useState
es un hook en React que permite añadir estado local a los componentes funcionales. Antes de la introducción de los hooks, el estado solo podía ser manejado en componentes de clase mediante el uso de this.state
y this.setState
. Con useState
, se puede manejar el estado en componentes funcionales de manera más sencilla y declarativa.
El uso de useState
implica la declaración de una variable de estado y una función para actualizar esa variable. Esta declaración se realiza mediante la desestructuración de un array devuelto por useState
. La sintaxis básica de useState
es la siguiente:
const [estado, setEstado] = useState(valorInicial);
estado
: representa el valor actual del estado.setEstado
: es una función que se utiliza para actualizar el valor del estado.valorInicial
: es el valor inicial del estado.
Ejemplo básico
A continuación se muestra un ejemplo básico de cómo utilizar useState
para manejar el estado de un contador en un componente funcional:
// Contador.jsx
import { useState } from 'react';
export default function Contador() {
const [contador, setContador] = useState(0);
const incrementar = () => {
setContador(contador + 1);
};
return (
<div>
<p>Contador: {contador}</p>
<button onClick={incrementar}>Incrementar</button>
</div>
);
}
En este ejemplo, useState
inicializa el estado contador
a 0. La función incrementar
actualiza el estado utilizando setContador
. Cada vez que se hace clic en el botón, setContador
incrementa el valor del contador y React vuelve a renderizar el componente con el nuevo estado.
Ejemplo con estado complejo
En situaciones donde el estado es más complejo, como un objeto, useState
también puede ser utilizado. Es importante tener en cuenta que, al actualizar el estado que es un objeto, se debe copiar el estado anterior y luego modificar las propiedades necesarias. Esto se puede hacer utilizando el spread operator(...
) o Object.assign
.
// PerfilUsuario.jsx
import { useState } from 'react';
export default function PerfilUsuario() {
const [usuario, setUsuario] = useState({
nombre: 'Juan',
edad: 30,
direccion: 'Calle Falsa 123'
});
const actualizarEdad = () => {
setUsuario(prevUsuario => ({
...prevUsuario,
edad: prevUsuario.edad + 1
}));
};
return (
<div>
<p>Nombre: {usuario.nombre}</p>
<p>Edad: {usuario.edad}</p>
<p>Dirección: {usuario.direccion}</p>
<button onClick={actualizarEdad}>Cumplir años</button>
</div>
);
}
En este ejemplo, useState
se utiliza para manejar el estado de un objeto usuario
. La función actualizarEdad
usa el valor previo del estado (prevUsuario
) y el spread operator(...
) para actualizar únicamente la propiedad edad
.
Consideraciones importantes
- Inicialización del estado: El valor inicial del estado solo se establece la primera vez que el componente se renderiza. Si el valor inicial depende de cálculos costosos, se puede pasar una función a
useState
para que se ejecute solo una vez.
const [valor, setValor] = useState(() => calcularValorInicial());
- Inmutabilidad: Es crucial no mutar directamente el estado anterior. En su lugar, se debe crear una nueva copia del estado con los cambios necesarios.
setUsuario(prevUsuario => ({
...prevUsuario,
nuevaPropiedad: nuevoValor
}));
- Renderización: Cada vez que se actualiza el estado usando
setEstado
, el componente se vuelve a renderizar. Esto puede afectar el rendimiento si no se maneja adecuadamente.
¿Qué es useReducer?
useReducer
es un hook en React que se utiliza para manejar el estado de los componentes funcionales, proporcionando una alternativa a useState
cuando se necesita manejar estados más complejos o con múltiples transiciones. Este hook es especialmente útil cuando las actualizaciones del estado dependen del estado anterior o cuando se requiere una lógica de actualización más sofisticada.
El uso de useReducer
implica tres elementos clave:
- Estado inicial: El estado con el que el hook comenzará a trabajar.
- Reducer: Una función que define cómo se debe actualizar el estado en respuesta a diferentes acciones.
- Dispatch: Una función que se utiliza para enviar acciones al reducer.
Sintaxis básica
La sintaxis básica de useReducer
es la siguiente:
const [state, dispatch] = useReducer(reducer, initialState);
state
: Representa el estado actual.dispatch
: Es una función que se utiliza para enviar acciones al reducer.reducer
: Es una función que toma el estado actual y una acción, y devuelve un nuevo estado.initialState
: Es el estado inicial del componente.
Ejemplo básico
A continuación se muestra un ejemplo básico de cómo utilizar useReducer
para manejar el estado de un contador:
// ContadorConReducer.jsx
import { useReducer } from 'react';
const initialState = { contador: 0 };
function reducer(state, action) {
switch (action.type) {
case 'incrementar':
return { contador: state.contador + 1 };
case 'decrementar':
return { contador: state.contador - 1 };
default:
throw new Error('Acción no soportada');
}
}
export default function ContadorConReducer() {
const [state, dispatch] = useReducer(reducer, initialState);
return (
<div>
<p>Contador: {state.contador}</p>
<button onClick={() => dispatch({ type: 'incrementar' })}>Incrementar</button>
<button onClick={() => dispatch({ type: 'decrementar' })}>Decrementar</button>
</div>
);
}
En este ejemplo, useReducer
se utiliza para manejar el estado del contador. El estado inicial es { contador: 0 }
y la función reducer
define cómo actualizar el estado en función de las acciones incrementar
y decrementar
. El dispatch
se utiliza para enviar las acciones correspondientes.
Cuando usar useReducer
useReducer
es más adecuado en las siguientes situaciones:
- Estados complejos: Cuando el estado es un objeto o un array con múltiples propiedades que necesitan ser actualizadas de manera coherente.
- Lógica de actualización compleja: Cuando las actualizaciones del estado dependen del estado anterior o requieren múltiples pasos.
- Escalabilidad: Cuando se espera que la lógica de actualización del estado crezca y se vuelva más compleja con el tiempo.
Ejemplo avanzado
Ejemplo más avanzado de useReducer
para manejar el estado de una lista de tareas:
// ListaDeTareas.jsx
import { useReducer } from 'react';
const initialState = { tareas: [] };
function reducer(state, action) {
switch (action.type) {
case 'agregar':
return { tareas: [...state.tareas, action.payload] };
case 'eliminar':
return { tareas: state.tareas.filter(tarea => tarea.id !== action.payload.id) };
case 'completar':
return {
tareas: state.tareas.map(tarea =>
tarea.id === action.payload.id ? { ...tarea, completada: !tarea.completada } : tarea
)
};
default:
throw new Error('Acción no soportada');
}
}
export default function ListaDeTareas() {
const [state, dispatch] = useReducer(reducer, initialState);
const agregarTarea = tarea => {
dispatch({ type: 'agregar', payload: tarea });
};
const eliminarTarea = id => {
dispatch({ type: 'eliminar', payload: { id } });
};
const completarTarea = id => {
dispatch({ type: 'completar', payload: { id } });
};
return (
<div>
<button onClick={() => agregarTarea({ id: Date.now(), texto: 'Nueva tarea', completada: false })}>
Agregar Tarea
</button>
<ul>
{state.tareas.map(tarea => (
<li key={tarea.id}>
<span style={{ textDecoration: tarea.completada ? 'line-through' : 'none' }}>
{tarea.texto}
</span>
<button onClick={() => completarTarea(tarea.id)}>
{tarea.completada ? 'Descompletar' : 'Completar'}
</button>
<button onClick={() => eliminarTarea(tarea.id)}>Eliminar</button>
</li>
))}
</ul>
</div>
);
}
En este ejemplo, useReducer
se utiliza para manejar una lista de tareas con acciones para agregar, eliminar y completar tareas. Este enfoque permite una gestión del estado más estructurada y escalable, adecuada para aplicaciones más complejas.
Cuando usar useState vs cuando usar useReducer
useState
y useReducer
son dos hooks en React que permiten manejar el estado local de un componente funcional. Sin embargo, cada uno tiene su propio conjunto de casos de uso y es importante saber cuándo utilizar uno sobre el otro.
Cuándo usar useState
useState
es ideal para manejar estados simples y es la elección más común cuando se cumplen las siguientes condiciones:
- Estado simple: Si el estado es un valor primitivo (como un número, string o booleano) o un objeto con pocas propiedades,
useState
es más que suficiente. - Actualizaciones independientes: Cuando las actualizaciones del estado no dependen del estado anterior,
useState
resulta más sencillo y directo. - Componentes individuales: Para componentes que no requieren una lógica de estado compleja y que son relativamente autónomos.
Cuándo usar useReducer
useReducer
es más adecuado para manejar estados complejos y lógicas de actualización sofisticadas. Se recomienda su uso en las siguientes situaciones:
- Estado complejo: Cuando el estado es un objeto o array con múltiples propiedades o elementos que necesitan ser actualizados de manera coherente.
- Lógica de actualización compleja: Cuando las actualizaciones del estado dependen del estado anterior o requieren una lógica de actualización más estructurada.
- Escalabilidad: Cuando se espera que la lógica de actualización del estado crezca y se vuelva más compleja con el tiempo.
- Mejor legibilidad: En situaciones donde la lógica de actualización del estado puede resultar en múltiples llamadas a
setState
,useReducer
puede mejorar la legibilidad y mantenibilidad del código.
Resumen de criterios de elección
- Utiliza
useState
para estados simples y cuando las actualizaciones no dependen del estado anterior. - Utiliza
useReducer
para estados complejos y cuando las actualizaciones del estado dependen del estado anterior o requieren una lógica de actualización más sofisticada.
Ejercicios de esta lección Estado local con useState y useReducer
Evalúa tus conocimientos de esta lección Estado local con useState y useReducer con nuestros retos de programación de tipo Test, Puzzle, Código y Proyecto con VSCode, guiados por IA.
Props y manejo de datos entre componentes
Definición y manejo de rutas
Conocimiento general de React
Galería de imágenes en React
Eventos en React
Gestor de tareas con React
Custom Hooks para servicios compartidos
Nuevos métodos create de React Router
Solicitudes HTTP con Fetch API
Instalar React y crear nuevo proyecto
Renderizado condicional
Introducción a JSX
Manejo de clases y estilos
Introducción a React Router
Solicitudes HTTP con Axios
Estado local con useState y useReducer
Estado global con Redux Toolkit
Estado y ciclo de vida de los componentes
Hooks para gestión de estado complejo y contexto
Componentes funcionales
Estado global con Context API
Hooks: optimización y concurrencia
Introducción a React y su ecosistema
Introducción a Componentes
Introducción a los Hooks
Navegación programática y redirección
Renderizado iterativo con bucles
Rutas anidadas y rutas dinámicas
Hooks: estado y efectos secundarios
Todas las lecciones de React
Accede a todas las lecciones de React y aprende con ejemplos prácticos de código y ejercicios de programación con IDE web sin instalar nada.
Introducción A React Y Su Ecosistema
Introducción Y Entorno
Instalar React Y Crear Nuevo Proyecto
Introducción Y Entorno
Introducción A Jsx
Componentes
Introducción A Componentes
Componentes
Componentes Funcionales
Componentes
Eventos En React
Componentes
Props Y Manejo De Datos Entre Componentes
Componentes
Renderizado Condicional
Componentes
Renderizado Iterativo Con Bucles
Componentes
Manejo De Clases Y Estilos
Componentes
Introducción A Los Hooks
Hooks
Estado Y Ciclo De Vida De Los Componentes
Hooks
Hooks Estado Y Efectos Secundarios
Hooks
Hooks Para Gestión De Estado Complejo Y Contexto
Hooks
Hooks Optimización Y Concurrencia
Hooks
Introducción A React Router
Navegación Y Enrutamiento
Definición Y Manejo De Rutas
Navegación Y Enrutamiento
Rutas Anidadas Y Rutas Dinámicas
Navegación Y Enrutamiento
Navegación Programática Redirección
Navegación Y Enrutamiento
Nuevos Métodos Create De React Router
Navegación Y Enrutamiento
Solicitudes Http Con Fetch Api
Interacción Http Con Backend
Solicitudes Http Con Axios
Interacción Http Con Backend
Estado Local Con Usestate Y Usereducer
Servicios Y Gestión De Estado
Estado Global Con Context Api
Servicios Y Gestión De Estado
Estado Global Con Redux Toolkit
Servicios Y Gestión De Estado
Custom Hooks Para Servicios Compartidos
Servicios Y Gestión De Estado
Evaluación Test React
Evaluación
Certificados de superación de React
Supera todos los ejercicios de programación del curso de React y obtén certificados de superación para mejorar tu currículum y tu empleabilidad.
En esta lección
Objetivos de aprendizaje de esta lección
- Comprender el concepto de estado local en React.
- Aprender a utilizar
useState
para manejar estados simples en componentes. - Conocer el uso de
useReducer
para gestionar estados más complejos. - Diferenciar cuándo usar
useState
yuseReducer
según el caso de uso. - Implementar actualizaciones de estado considerando la inmutabilidad y rendimiento.
- Aplicar técnicas avanzadas de gestión de estado en componentes funcionales.