Curso react nivel medio
Introducción
Los Custom Hooks son funciones de JavaScript que permiten reutilizar lógica en componentes funcionales de React. Si tienes lógica que se repite en varios componentes, los Custom Hooks te ayudan a encapsularla, haciendo que tu código sea más limpio y fácil de mantener.
¿Qué son los Custom Hooks?
Un Custom Hook es básicamente una función que utiliza uno o más Hooks de React (como useState, useEffect, useContext, etc.) para encapsular lógica reutilizable.
Los Custom Hooks siempre comienzan con el prefijo use (por ejemplo: useAuth, useFetch, useForm).
¿Cómo Crear un Custom Hook?
Ejemplo Básico: useContador
Supongamos que quieres manejar un contador en varios componentes. Podemos encapsular la lógica en un Custom Hook.
1import { useState } from "react"; 2 3function useContador(valorInicial = 0) { 4 const [contador, setContador] = useState(valorInicial); 5 6 const incrementar = () => setContador(contador + 1); 7 const decrementar = () => setContador(contador - 1); 8 const reiniciar = () => setContador(valorInicial); 9 10 return { contador, incrementar, decrementar, reiniciar }; 11} 12 13export default useContador;
Usando el Custom Hook
1import React from "react"; 2import useContador from "./useContador"; 3 4function Contador() { 5 const { contador, incrementar, decrementar, reiniciar } = useContador(10); 6 7 return ( 8 <div> 9 <p>Contador: {contador}</p> 10 <button onClick={incrementar}>Incrementar</button> 11 <button onClick={decrementar}>Decrementar</button> 12 <button onClick={reiniciar}>Reiniciar</button> 13 </div> 14 ); 15} 16 17export default Contador;
Explicación
useContadorencapsula la lógica del contador y devuelve métodos (incrementar,decrementar, etc.) junto con el estado actual.- El componente
Contadorutiliza esta lógica sin repetirla.
Custom Hook con useEffect: useFetch
Encapsulemos la lógica para hacer una petición a una API.
Hook useFetch
1import { useState, useEffect } from "react"; 2 3function useFetch(url) { 4 const [data, setData] = useState(null); 5 const [loading, setLoading] = useState(true); 6 const [error, setError] = useState(null); 7 8 useEffect(() => { 9 const fetchData = async () => { 10 try { 11 const response = await fetch(url); 12 if (!response.ok) { 13 throw new Error("Error al obtener los datos"); 14 } 15 const result = await response.json(); 16 setData(result); 17 } catch (err) { 18 setError(err.message); 19 } finally { 20 setLoading(false); 21 } 22 }; 23 24 fetchData(); 25 }, [url]); 26 27 return { data, loading, error }; 28} 29 30export default useFetch;
Usando el Hook useFetch
1import React from "react"; 2import useFetch from "./useFetch"; 3 4function ListaUsuarios() { 5 const { data, loading, error } = useFetch( 6 "https://jsonplaceholder.typicode.com/users" 7 ); 8 9 if (loading) return <p>Cargando...</p>; 10 if (error) return <p>Error: {error}</p>; 11 12 return ( 13 <ul> 14 {data.map((usuario) => ( 15 <li key={usuario.id}>{usuario.name}</li> 16 ))} 17 </ul> 18 ); 19} 20 21export default ListaUsuarios;
Explicación
useFetchencapsula la lógica para realizar la petición a la API.- El componente
ListaUsuariosutiliza el hook y se centra solo en el renderizado, sin preocuparse por la lógica de la petición.
Custom Hook con useContext: useAuth
Si usas un contexto para manejar la autenticación, puedes crear un Custom Hook para facilitar el acceso a los datos.
Hook useAuth
1import { useContext } from "react"; 2import AuthContext from "./AuthContext"; 3 4function useAuth() { 5 return useContext(AuthContext); 6} 7 8export default useAuth;
Usando el Hook useAuth
1import React from "react"; 2import useAuth from "./useAuth"; 3 4function PerfilUsuario() { 5 const { usuario, logout } = useAuth(); 6 7 return ( 8 <div> 9 <p>Nombre: {usuario.nombre}</p> 10 <button onClick={logout}>Cerrar sesión</button> 11 </div> 12 ); 13} 14 15export default PerfilUsuario;
Explicación
useAuthsimplifica el acceso al contexto de autenticación (AuthContext).- Cualquier componente que necesite datos del usuario puede usar
useAuth.
Ventajas de los Custom Hooks
-
Reutilización de Lógica
Puedes usar el mismo Custom Hook en varios componentes sin duplicar código. -
Código más Limpio
Los componentes se enfocan solo en la UI, delegando la lógica al Custom Hook. -
Modularidad
Si necesitas cambiar la lógica de un Custom Hook, afecta a todos los componentes que lo usan.
Consideraciones al Crear Custom Hooks
-
Prefijo
use
Siempre usa el prefijousepara que React pueda identificarlo como un hook y aplicar las reglas de los hooks. -
Reglas de los Hooks
Los Custom Hooks siguen las mismas reglas que otros hooks:- Deben llamarse al inicio de un componente.
- No deben usarse dentro de condicionales o bucles.
-
Nombre Descriptivo
El nombre del Custom Hook debe describir su propósito (useForm,useCart, etc.).
Ejemplo Avanzado: useForm
Un Custom Hook para manejar formularios.
Hook useForm
1import { useState } from "react"; 2 3function useForm(initialValues) { 4 const [values, setValues] = useState(initialValues); 5 6 const handleChange = (e) => { 7 const { name, value } = e.target; 8 setValues({ ...values, [name]: value }); 9 }; 10 11 const reset = () => setValues(initialValues); 12 13 return { values, handleChange, reset }; 14} 15 16export default useForm;
Usando el Hook useForm
1import React from "react"; 2import useForm from "./useForm"; 3 4function Formulario() { 5 const { values, handleChange, reset } = useForm({ 6 nombre: "", 7 correo: "", 8 }); 9 10 const handleSubmit = (e) => { 11 e.preventDefault(); 12 console.log("Datos enviados:", values); 13 reset(); 14 }; 15 16 return ( 17 <form onSubmit={handleSubmit}> 18 <input 19 type="text" 20 name="nombre" 21 value={values.nombre} 22 onChange={handleChange} 23 placeholder="Nombre" 24 /> 25 <input 26 type="email" 27 name="correo" 28 value={values.correo} 29 onChange={handleChange} 30 placeholder="Correo" 31 /> 32 <button type="submit">Enviar</button> 33 </form> 34 ); 35} 36 37export default Formulario;
Conclusión
Los Custom Hooks son una forma poderosa y eficiente de reutilizar lógica en React. Ayudan a mantener tus componentes funcionales más enfocados en el renderizado, dejando la lógica reutilizable encapsulada en funciones.