React Custom Hooks: Reutiliza tu lógica

Aprende a crear custom hooks poderosos para compartir lógica entre componentes

CodeCraft Master
17 de febrero de 2026
19 min
3865 views

React Custom Hooks: Reutiliza tu lógica

Los custom hooks te permiten extraer lógica de componentes en funciones reutilizables, haciendo tu código más limpio y mantenible.

Tu primer custom hook: useFetch

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 {
        setLoading(true);
        const response = await fetch(url);
        const json = await response.json();
        setData(json);
      } catch (err) {
        setError(err);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, loading, error };
}

// Uso
function UserProfile({ userId }) {
  const { data, loading, error } = useFetch(`/api/users/${userId}`);

  if (loading) return <p>Cargando...</p>;
  if (error) return <p>Error: {error.message}</p>;
  return <div>{data.name}</div>;
}

useLocalStorage: Persistencia simple

import { useState, useEffect } from 'react';

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

  useEffect(() => {
    try {
      window.localStorage.setItem(key, JSON.stringify(value));
    } catch (error) {
      console.error(error);
    }
  }, [key, value]);

  return [value, setValue];
}

// Uso
function Settings() {
  const [theme, setTheme] = useLocalStorage('theme', 'light');
  
  return (
    <button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
      Tema actual: {theme}
    </button>
  );
}

useDebounce: Optimiza búsquedas

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;
}

// Uso
function SearchBar() {
  const [searchTerm, setSearchTerm] = useState('');
  const debouncedSearchTerm = useDebounce(searchTerm, 500);

  useEffect(() => {
    if (debouncedSearchTerm) {
      // Hacer búsqueda solo después de 500ms de inactividad
      console.log('Buscando:', debouncedSearchTerm);
    }
  }, [debouncedSearchTerm]);

  return (
    <input
      value={searchTerm}
      onChange={(e) => setSearchTerm(e.target.value)}
      placeholder="Buscar..."
    />
  );
}

useWindowSize: Responsive hooks

import { useState, useEffect } from 'react';

function useWindowSize() {
  const [windowSize, setWindowSize] = useState({
    width: undefined,
    height: undefined,
  });

  useEffect(() => {
    function handleResize() {
      setWindowSize({
        width: window.innerWidth,
        height: window.innerHeight,
      });
    }

    window.addEventListener('resize', handleResize);
    handleResize();

    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return windowSize;
}

// Uso
function ResponsiveComponent() {
  const { width } = useWindowSize();
  
  return (
    <div>
      {width < 768 ? (
        <MobileLayout />
      ) : (
        <DesktopLayout />
      )}
    </div>
  );
}

useToggle: Booleanos simplificados

import { useState } from 'react';

function useToggle(initialValue = false) {
  const [value, setValue] = useState(initialValue);

  const toggle = () => setValue(prev => !prev);
  const setTrue = () => setValue(true);
  const setFalse = () => setValue(false);

  return [value, { toggle, setTrue, setFalse }];
}

// Uso
function Modal() {
  const [isOpen, { toggle, setFalse }] = useToggle();

  return (
    <>
      <button onClick={toggle}>Abrir Modal</button>
      {isOpen && (
        <div className="modal">
          <p>Contenido del modal</p>
          <button onClick={setFalse}>Cerrar</button>
        </div>
      )}
    </>
  );
}

usePrevious: Acceder al valor anterior

import { useRef, useEffect } from 'react';

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

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

  return ref.current;
}

// Uso
function Counter() {
  const [count, setCount] = useState(0);
  const prevCount = usePrevious(count);

  return (
    <div>
      <p>Ahora: {count}</p>
      <p>Antes: {prevCount}</p>
      <button onClick={() => setCount(count + 1)}>Incrementar</button>
    </div>
  );
}

useForm: Manejo de formularios

import { useState } from 'react';

function useForm(initialValues) {
  const [values, setValues] = useState(initialValues);

  const handleChange = (e) => {
    const { name, value } = e.target;
    setValues(prev => ({
      ...prev,
      [name]: value
    }));
  };

  const reset = () => setValues(initialValues);

  return { values, handleChange, reset };
}

// Uso
function LoginForm() {
  const { values, handleChange, reset } = useForm({
    email: '',
    password: ''
  });

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log(values);
    reset();
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        name="email"
        value={values.email}
        onChange={handleChange}
      />
      <input
        name="password"
        type="password"
        value={values.password}
        onChange={handleChange}
      />
      <button type="submit">Iniciar sesión</button>
    </form>
  );
}

Reglas de los Custom Hooks

  1. Siempre comienza con "use": useNombreDescriptivo
  2. Sigue las reglas de hooks: Solo llamar en el nivel superior
  3. Mantén la independencia: No dependas de contexto externo innecesario
  4. Documenta bien: Especialmente los parámetros y valores de retorno

Conclusión

Los custom hooks son una herramienta fundamental para crear aplicaciones React mantenibles. Te permiten compartir lógica compleja de manera simple y declarativa.

C

CodeCraft Master

Desarrollador Full Stack apasionado por compartir conocimiento. Escribo sobre JavaScript, TypeScript, React y desarrollo web moderno.

Artículos Relacionados

Únete a nuestro boletín

Recibe contenido exclusivo de desarrollo web directamente en tu bandeja de entrada.

  • Contenido exclusivo de desarrollo web

  • Actualizaciones semanales

  • Tips y trucos

  • Sin spam, solo contenido de calidad

Al suscribirte, aceptas recibir correos electrónicos. Puedes cancelar tu suscripción en cualquier momento.