Curso react nivel medio
Los Hooks son funciones especiales en React que permiten usar estado y otras características avanzadas en componentes de función, sin necesidad de usar clases. Los Hooks más comunes son useState y useEffect, pero existen otros que nos ayudan a manejar distintos aspectos de nuestras aplicaciones.
1. Introducción a los Hooks
Antes de los Hooks, los componentes de clase eran necesarios para manejar el estado y el ciclo de vida en React. Con los Hooks, podemos hacer esto y más en componentes de función, lo que simplifica el código y mejora la legibilidad.
Reglas de los Hooks:
- Los Hooks deben usarse solo en componentes de función.
- Deben estar en el nivel superior del componente, nunca dentro de bucles, condicionales o funciones anidadas.
2. Hook useEffect para efectos secundarios
useEffect es un Hook que permite manejar efectos secundarios en los componentes, como hacer peticiones de datos, suscribirse a servicios externos, o manipular el DOM directamente. Este Hook se ejecuta después de que React haya renderizado el componente, y puede configurarse para ejecutarse solo en momentos específicos.
Ejemplo de useEffect:
1import React, { useEffect, useState } from 'react'; 2 3function Reloj() { 4 const [hora, setHora] = useState(new Date()); 5 6 useEffect(() => { 7 const intervalo = setInterval(() => { 8 setHora(new Date()); 9 }, 1000); 10 11 return () => clearInterval(intervalo); // Limpieza del efecto 12 }, []); // El array vacío significa que el efecto solo se ejecuta una vez 13 14 return <h1>{hora.toLocaleTimeString()}</h1>; 15} 16 17export default Reloj;
En este ejemplo:
useEffectcrea un intervalo que actualiza el estadohoracada segundo.- La función de limpieza (
clearInterval) se ejecuta cuando el componente se desmonta, evitando que el intervalo siga corriendo en segundo plano. - El
[]como segundo parámetro indica que el efecto se ejecuta solo al montar el componente.
3. Otros Hooks útiles
-
useContext: Permite acceder a datos compartidos en toda la aplicación sin necesidad de pasar props manualmente a través de cada componente. Es útil para manejar temas (claro/oscuro), idioma, autenticación, etc.1const TemaContext = React.createContext(); 2 3function Componente() { 4 const tema = useContext(TemaContext); 5 return <p>El tema actual es {tema}</p>; 6} -
useReducer: Es útil para manejar estados complejos, como en aplicaciones con lógica avanzada. Funciona de manera similar auseState, pero utiliza un “reductor” que especifica cómo cambia el estado.1const reducer = (state, action) => { 2 switch (action.type) { 3 case 'incrementar': 4 return { contador: state.contador + 1 }; 5 default: 6 return state; 7 } 8}; 9 10function Contador() { 11 const [state, dispatch] = useReducer(reducer, { contador: 0 }); 12 13 return ( 14 <div> 15 <p>Contador: {state.contador}</p> 16 <button onClick={() => dispatch({ type: 'incrementar' })}>Incrementar</button> 17 </div> 18 ); 19} -
useRef: Nos da una referencia mutable a un elemento del DOM. Es ideal para acceder directamente a un elemento sin causar un renderizado.1function EnfoqueInput() { 2 const inputRef = useRef(); 3 4 const enfocar = () => { 5 inputRef.current.focus(); 6 }; 7 8 return ( 9 <div> 10 <input ref={inputRef} placeholder="Escribe algo..." /> 11 <button onClick={enfocar}>Enfocar</button> 12 </div> 13 ); 14} -
useMemo: Memoriza el resultado de una función para evitar cálculos innecesarios en cada renderizado. Se usa cuando una operación es costosa (como un cálculo complejo o procesamiento de listas grandes).1const valorMemoizado = useMemo(() => calcularValorComplejo(datos), [datos]); -
useCallback: Memoriza una función, evitando que se vuelva a crear en cada renderizado, lo que puede ser útil en componentes que reciben funciones como props.1const funcionMemoizada = useCallback(() => { 2 console.log("Función memorizada"); 3}, []);
4. Ejercicio práctico: Fetch de datos usando useEffect
Vamos a crear un componente que obtenga datos de una API usando useEffect. En este ejemplo, haremos una petición a una API de usuarios y mostraremos los nombres en pantalla.
1import React, { useEffect, useState } from 'react'; 2 3function ListaDeUsuarios() { 4 const [usuarios, setUsuarios] = useState([]); 5 const [cargando, setCargando] = useState(true); 6 7 useEffect(() => { 8 // Función para obtener datos 9 const obtenerUsuarios = async () => { 10 try { 11 const respuesta = await fetch('https://jsonplaceholder.typicode.com/users'); 12 const datos = await respuesta.json(); 13 setUsuarios(datos); 14 } catch (error) { 15 console.error("Error al obtener los usuarios:", error); 16 } finally { 17 setCargando(false); // Oculta el mensaje de carga cuando finaliza 18 } 19 }; 20 21 obtenerUsuarios(); 22 }, []); // El array vacío hace que el efecto se ejecute solo una vez 23 24 return ( 25 <div> 26 <h1>Lista de Usuarios</h1> 27 {cargando ? ( 28 <p>Cargando...</p> 29 ) : ( 30 <ul> 31 {usuarios.map((usuario) => ( 32 <li key={usuario.id}>{usuario.name}</li> 33 ))} 34 </ul> 35 )} 36 </div> 37 ); 38} 39 40export default ListaDeUsuarios;
En este ejercicio:
- Creamos dos estados:
usuariospara almacenar la lista de usuarios ycargandopara controlar si los datos están siendo cargados. useEffectejecutaobtenerUsuariossolo una vez cuando el componente se monta.obtenerUsuarioses una función asíncrona que hace una petición a la API de usuarios y actualiza el estadousuarioscon los datos obtenidos.- Si los datos están cargando, mostramos un mensaje de "Cargando...", y cuando terminan de cargar, mostramos la lista de usuarios.
Este ejercicio combina useEffect con una llamada a la API, lo cual es muy común en aplicaciones React para manejar datos dinámicos.
- Loading...