Qué son los Custom Hooks en React

Los custom hooks en React son funciones de JavaScript que comienzan con el prefijo use y te permiten reutilizar lógica de estado o de efectos entre componentes de manera sencilla y organizada. Básicamente, puedes pensar en un custom hook como una forma de encapsular lógica repetitiva para no tener que repetir el mismo código en varios componentes.

  Ventajas de los Custom Hooks

  • Reutilización de Lógica: Evitan duplicación de código al centralizar la lógica en un solo lugar.
  • Mejor Organización: Simplifican los componentes y los hacen más fáciles de mantener.
  • Separación de Responsabilidades: Permiten dividir la lógica de negocio de la interfaz del usuario.

1. Ejemplo de un Custom Hook

Imagina que quieres hacer una solicitud HTTP en varios componentes. Puedes crear un custom hook para manejar la lógica de las solicitudes:

jsx
// useFetch.js
import { useState, useEffect } from 'react';

function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

useEffect(() => {
  const fetchData = async () => {
    try {
      const response = await fetch(url);
      const result = await response.json();
      setData(result);
    } catch (error) {
      setError(error);
    } finally {
      setLoading(false);
    }
  };
  fetchData();
}, [url]);

return { data, loading, error };
}

export default useFetch;

Luego, puedes usar useFetch en tus componentes de forma simple:

jsx
import useFetch from './useFetch';

function MyComponent() {
const { data, loading, error } = useFetch('https://api.example.com/data');

if (loading) return <p>Loading...</p>;
if (error) return <p>Error: {error.message}</p>;

return (
  <div>
    {data && data.map(item => (
      <p key={item.id}>{item.name}</p>
    ))}
  </div>
);
}

2. useLocalStorage

Guarda y obtiene valores desde el almacenamiento local del navegador. Esto es ideal para guardar datos que deben persistir entre recargas, como temas, configuraciones de usuario, etc.

jsx
// useLocalStorage.js
import { useState } from 'react';

function useLocalStorage(key, initialValue) {
const [storedValue, setStoredValue] = useState(() => {
  try {
    const item = window.localStorage.getItem(key);
    return item ? JSON.parse(item) : initialValue;
  } catch (error) {
    console.error(error);
    return initialValue;
  }
});

const setValue = value => {
  try {
    setStoredValue(value);
    window.localStorage.setItem(key, JSON.stringify(value));
  } catch (error) {
    console.error(error);
  }
};

return [storedValue, setValue];
}

export default useLocalStorage;
  Uso

Este ejemplo almacena el tema de la aplicación (theme) en el localStorage del navegador. useLocalStorage inicia el valor en ‘light’ y permite actualizarlo con setTheme.

jsx
const [theme, setTheme] = useLocalStorage('theme', 'light');

3. useToggle

Cambia entre true y false, ideal para manejar estados de apertura y cierre de modales, mostrar/ocultar elementos, etc.

jsx
// useToggle.js
import { useState } from 'react';

function useToggle(initialValue = false) {
const [state, setState] = useState(initialValue);

const toggle = () => setState(prev => !prev);

return [state, toggle];
}

export default useToggle;
  Uso

Este hook inicializa isModalOpen en false y alterna su valor entre true y false cada vez que llamas a toggleModal(). Ideal para manejar la apertura/cierre de modales.

jsx
const [isModalOpen, toggleModal] = useToggle(false);

// Llamar a `toggleModal()` cambia el estado de `isModalOpen` entre `true` y `false`

4. usePrevious

Almacena el valor anterior de una variable o estado, útil para comparar el valor actual con el previo.

jsx
// usePrevious.js
import { useEffect, useRef } from 'react';

function usePrevious(value) {
const ref = useRef();

useEffect(() => {
  ref.current = value;
}, [value]);

return ref.current;
}

export default usePrevious;
  Uso

Aquí, usePrevious guarda el valor anterior de count en prevCount, permitiendo compararlo con el valor actual. Ideal para ver cambios en el estado entre renders.

jsx
const [count, setCount] = useState(0);
const prevCount = usePrevious(count);

// `prevCount` almacena el valor anterior de `count`

5. useDebounce

Retrasa la actualización de un valor durante un tiempo específico. Es útil en inputs que disparan llamadas de API, como búsqueda en tiempo real.

jsx
// useDebounce.js
import { useState, useEffect } from 'react';

function useDebounce(value, delay) {
const [debouncedValue, setDebouncedValue] = useState(value);

useEffect(() => {
  const handler = setTimeout(() => {
    setDebouncedValue(value);
  }, delay);

  return () => clearTimeout(handler);
}, [value, delay]);

return debouncedValue;
}

export default useDebounce;
  Uso

Este hook useDebounce retrasa la actualización de debouncedSearchTerm 500 ms después de cada cambio en searchTerm, útil para optimizar búsquedas en tiempo real y evitar llamadas excesivas a la API.

jsx
const [searchTerm, setSearchTerm] = useState('');
const debouncedSearchTerm = useDebounce(searchTerm, 500);

// `debouncedSearchTerm` se actualiza solo después de 500 ms sin cambios en `searchTerm`
  Resumen

Estos custom hooks ofrecen soluciones prácticas para problemas comunes en desarrollo de aplicaciones React. Cada uno encapsula lógica específica que puedes reutilizar en diferentes componentes, ¡mejorando la eficiencia y la limpieza del código!