Un hook en React es una función especial que te permite «enganchar» características de React (como el estado y el ciclo de vida) en componentes funcionales. Los dos hooks más comunes son useState
(para gestionar el estado) y useEffect
(para manejar efectos secundarios), aunque puedes crear tus propios hooks personalizados para encapsular lógica reutilizable.
Aquí tienes una guía paso a paso para crear un hook personalizado en React:
1. Estructura Básica de un Hook Personalizado
Un hook personalizado es una función de JavaScript que sigue el formato useNombreDelHook
. Para que React lo reconozca como un hook, el nombre de la función debe comenzar con use
.
// Ejemplo de un hook personalizado export const useUtils = () => { const context = useContext(UtilsContext); if (!context) { throw new Error('useUtils must be used within a UtilsProvider'); } return context; };
2. Ejemplo Práctico: Hook que contiene un modal
Aquí crearemos un hook personalizado llamado useUtils que contendrá un modal. Además nos servirá para añadir el resto de elementos utils que podamos necesitar.
Paso 1: Crear el Hook
Crea un archivo llamado utilsContext.tsx
(estoy usando Typescript):
import AlertDialog, { mostrarAlerta as mostrarAlertaFunc, AlertParams } from '@/components/elements/Dialog'; // Crear el contexto const UtilsContext = createContext<{ mostrarAlerta: (params: AlertParams) => void; } | undefined>(undefined); export const UtilsProvider: React.FC<{ children: React.ReactNode}> = ({ children}) => { return ( <UtilsContext.Provider value={ { mostrarAlerta, } }> {children} <AlertDialog /> </UtilsContext.Provider> ); }; export const useUtils = () => { const context = useContext(UtilsContext); if (!context) { throw new Error('useUtils must be used within a UtilsProvider'); } return context; };
Creamos el componente modal llamado alertDialog.tsx
// components/AlertDialog.js import React, { useState } from 'react'; let setOpenExt; let setParamsExt; const AlertDialog = () => { const [open, setOpen] = useState(false); const [props, setParams] = useState({}); setOpenExt = setOpen; setParamsExt = (params) => { setParams(params); }; const handleClose = () => { setOpen(false); if (props.onCancel) props.onCancel(); }; const handleAgree = () => { setOpen(false); if (props.onAccept) props.onAccept(); }; return open ? ( <div className="modal-overlay"> <div className="modal-content"> <div className="modal-header"> <h3>{props.title}</h3> </div> <div className="modal-body"> <p>{props.content}</p> </div> <div className="modal-footer"> {props.showCancelButton && ( <button onClick={handleClose} className="modal-button cancel-button"> {props.cancelText || "Cancelar"} </button> )} <button onClick={handleAgree} className="modal-button accept-button"> {props.acceptText || "Aceptar"} </button> </div> </div> </div> ) : null; }; export default AlertDialog; export const mostrarAlerta = (params) => { setOpenExt(true); setParamsExt(params); };
Estilos CSS (importarlos en app.tsx):
/* styles.css */ .modal-overlay { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background: rgba(0, 0, 0, 0.5); display: flex; justify-content: center; align-items: center; z-index: 9999; } .modal-content { background: white; padding: 20px; border-radius: 8px; max-width: 500px; min-width: 300px; width: 100%; display: flex; flex-direction: column; gap: 10px; } .modal-header h3 { margin: 0; font-size: 1.25em; } .modal-body p { margin: 0; } .modal-footer { display: flex; justify-content: flex-end; gap: 10px; } .modal-button { padding: 10px 20px; border: none; font-weight: bold; cursor: pointer; } .accept-button { background-color: #007bff; color: white; } .cancel-button { background-color: #dc3545; color: white; }
Paso 2: Usar el Hook en un Componente
Ahora que tienes el hook, para utilizarlo primero tenemos que envolver el componente o el arbol de componentes de la siguiente forma:
- Vamos a app.tsx:
return ( <ThemeProvider> <UtilsProvider> <main style={{ marginTop: "60px", paddingTop: "20px", paddingBottom: "16px" }}> <Component pathActual={pathActual} {...rest} /> </main> </UtilsProvider> </ThemeProvider> );
En mi caso ya tenía el hook ThemeProvider.
He envuelto todo el árbol de la página con UtilsProvider.
Y ahora podremos utilizarlo de esta forma:
Solo tendríamos qué llamar al modal de la siguiente forma:
const mostrarModal = () => { mostrarAlerta({ title: "Confirmación", content: "¿Estás seguro de que quieres continuar?", acceptText: "Aceptar", cancelText: "Cancelar", showCancelButton: true, onAccept: () => alert("Has aceptado"), onCancel: () => alert("Has cancelado") }); };
Si nuestro hook contiene funciones qué podemos invocar tendremos que importar en nuestro componente el hook personalizado de la siguiente forma:
const {mostrarAlerta} = useUtils();
¿Por qué Crear Hooks Personalizados?
Los hooks personalizados te ayudan a encapsular lógica compleja y repetitiva, haciendo tu código más limpio y reutilizable en múltiples componentes.
Ingeniero en Informática, me encanta crear cosas o arreglarlas y darles una nueva vida. Escritor y poeta. Más de 20 APPs publicadas y un libro en Amazon.