logo-andres-saumet

logo-andres-saumet
React Hooks: Guía Definitiva para Desarrolladores Modernos
7 de febrero de 2026

React Hooks: Guía Definitiva para Desarrolladores Modernos

Domina los React Hooks. Aprende useState, useEffect, useContext, useReducer y cómo crear tus propios custom hooks.

AS
Andres Saumet
reactjavascripthooksdevelopment

React Hooks: Guía Definitiva para Desarrolladores Modernos

Los React Hooks revolucionaron completamente la forma en que escribimos componentes React, eliminando la necesidad de componentes de clase y permitiendo reutilizar lógica de estado de manera más elegante y eficiente. Esta guía definitiva te enseña todo lo que necesitas saber sobre React Hooks, desde useState y useEffect hasta la creación de custom hooks avanzados.

¿Qué son los React Hooks y por qué son importantes?

Los React Hooks son funciones especiales que te permiten "engancharte" (hook into) características de React desde componentes funcionales. Introducidos en React 16.8, los Hooks eliminaron la complejidad de los componentes de clase y abrieron un nuevo paradigma para escribir componentes React.

Antes de los Hooks (React Class Components)

  • Sintaxis compleja con this.state y this.setState
  • Lógica de ciclo de vida dispersa en múltiples métodos
  • Dificultad para reutilizar lógica entre componentes
  • Mayor tamaño de bundle

Los Hooks resuelven todos estos problemas proporcionando una forma más simple, modular y reutilizable de manejar estado y efectos secundarios en componentes funcionales.

useState Hook - Agregando estado a componentes funcionales

useState es el hook más fundamental y el que usarás con mayor frecuencia. Permite agregar estado a componentes funcionales sin necesidad de convertirlos en componentes de clase.

Sintaxis básica de useState

import { useState } from 'react';

function Counter() {
  // Desestructuramos [valor, función para actualizar]
  const [count, setCount] = useState(0);

  return (
    <>
      <p>Contador: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Incrementar
      </button>
    </>
  );
}

Parámetros y retorno de useState

  • Parámetro: Valor inicial del estado (puede ser cualquier tipo: number, string, object, array)
  • Retorna: Array con [estado actual, función para actualizar]
  • Función actualizadora: Puede recibir un valor o una función (para acceder al estado anterior)

Actualizar estado basado en estado anterior

// ✅ Correcto - usando función
const [count, setCount] = useState(0);
setCount(prevCount => prevCount + 1);

// ❌ Incorrecto - pueden perderse actualizaciones
setCount(count + 1);
setCount(count + 1);

Casos de uso avanzados de useState

// Estado con objeto complejo
const [user, setUser] = useState({ name: '', email: '' });

// Actualizar propiedad específica
setUser({ ...user, name: 'Juan' });

// Estado con array
const [todos, setTodos] = useState([]);
setTodos([...todos, { id: 1, title: 'Tarea nueva' }]);

// Función de inicialización (lazy initialization)
const [state, setState] = useState(() => {
  console.log('Inicialización costosa');
  return computeExpensiveValue();
});

useEffect Hook - Manejando efectos secundarios

useEffect permite ejecutar código cuando el componente se monta, actualiza o desmonta. Reemplaza los métodos de ciclo de vida componentDidMount, componentDidUpdate y componentWillUnmount.

Sintaxis básica de useEffect

import { useEffect } from 'react';

function DataFetcher() {
  const [data, setData] = useState(null);

  useEffect(() => {
    // Este código se ejecuta después de cada render
    console.log('Componente montado o actualizado');

    // Cleanup function (opcional)
    return () => {
      console.log('Limpiando recursos');
    };
  }); // Sin dependency array - se ejecuta siempre
}

Dependency Array - Controlando cuándo se ejecuta useEffect

// Se ejecuta solo al montar el componente
useEffect(() => {
  console.log('Montado');
}, []);

// Se ejecuta cuando userId cambia
useEffect(() => {
  fetchUserData(userId);
}, [userId]);

// Se ejecuta después de cada render
useEffect(() => {
  console.log('Render completado');
});

Patrones comunes con useEffect

Fetching de datos

useEffect(() => {
  let isMounted = true;

  const fetchData = async () => {
    const response = await fetch('/api/users');
    const data = await response.json();
    if (isMounted) {
      setUsers(data);
    }
  };

  fetchData();

  return () => {
    isMounted = false; // Evita memory leaks
  };
}, []);

Event listeners

useEffect(() => {
  const handleResize = () => {
    setWidth(window.innerWidth);
  };

  window.addEventListener('resize', handleResize);

  // Cleanup: remover listener
  return () => window.removeEventListener('resize', handleResize);
}, []);

Hooks adicionales - La caja de herramientas de React

useContext - Compartir datos sin prop drilling

useContext te permite acceder a valores del Context sin necesidad de anidar componentes Consumer.

const ThemeContext = React.createContext('light');

function ThemedComponent() {
  const theme = useContext(ThemeContext);
  return <div className={theme}>Contenido</div>;
}

useReducer - Estado complejo con múltiples acciones

Para estado más complejo que useState, useReducer proporciona un patrón Redux-like.

const initialState = { count: 0 };

function reducer(state, action) {
  switch(action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <>
      <p>Contador: {state.count}</p>
      <button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button>
      <button onClick={() => dispatch({ type: 'DECREMENT' })}>-</button>
    </>
  );
}

useCallback - Memorizar funciones

Evita crear nuevas funciones en cada render, importante para optimización con React.memo.

const memoizedCallback = useCallback(() => {
  doSomething(a, b);
}, [a, b]); // Solo se recrea si a o b cambian

useMemo - Memorizar valores computados

Evita cálculos costosos innecesarios.

const memoizedValue = useMemo(() => {
  return expensiveCalculation(a, b);
}, [a, b]);

useRef - Referencias directas al DOM

Accede directamente a elementos del DOM sin afectar el re-render.

function TextInput() {
  const inputRef = useRef(null);

  const focusInput = () => {
    inputRef.current.focus();
  };

  return (
    <>
      <input ref={inputRef} />
      <button onClick={focusInput}>Enfocar</button>
    </>
  );
}

Creando Custom Hooks - Lógica reutilizable

Los Custom Hooks son funciones que usan otros hooks. Permiten extraer y compartir lógica entre componentes de manera elegante.

Reglas para crear Custom Hooks

  1. El nombre debe empezar con "use" (useMyHook)
  2. Solo puede ser llamado desde componentes React u otros hooks
  3. Debe ser llamado en el nivel superior del componente

Ejemplo: useFormInput - Custom Hook para formularios

function useFormInput(initialValue = '') {
  const [value, setValue] = useState(initialValue);

  return {
    value,
    bind: {
      value,
      onChange: e => setValue(e.target.value)
    },
    reset: () => setValue(initialValue)
  };
}

// Uso
function LoginForm() {
  const email = useFormInput('');
  const password = useFormInput('');

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log(email.value, password.value);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input {...email.bind} type="email" />
      <input {...password.bind} type="password" />
      <button type="submit">Login</button>
      <button type="button" onClick={password.reset}>Resetear</button>
    </form>
  );
}

Ejemplo: useFetch - Custom Hook para peticiones HTTP

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

  useEffect(() => {
    let isMounted = true;

    fetch(url)
      .then(res => res.json())
      .then(data => {
        if (isMounted) {
          setData(data);
          setLoading(false);
        }
      })
      .catch(err => {
        if (isMounted) {
          setError(err);
          setLoading(false);
        }
      });

    return () => { isMounted = false; };
  }, [url]);

  return { data, loading, error };
}

// Uso
function UserList() {
  const { data: users, loading, error } = useFetch('/api/users');

  if (loading) return <p>Cargando...</p>;
  if (error) return <p>Error</p>;

  return (
    <ul>
      {users.map(user => <li key={user.id}>{user.name}</li>)}
    </ul>
  );
}

Mejores prácticas con Hooks

✅ Haz esto

  • Llama hooks en el nivel superior del componente
  • Usa dependency arrays correctamente en useEffect
  • Extrae lógica en custom hooks para reutilización
  • Usa useCallback y useMemo solo cuando sea necesario
  • Mantén hooks simples y enfocados en una tarea

❌ Evita esto

  • Llamar hooks dentro de condicionales o loops
  • Omitir dependencias en dependency arrays
  • Crear hooks sin el prefijo "use"
  • Sobreoptimizar con useMemo y useCallback
  • Usar hooks en componentes de clase

Conclusión: Domina React Hooks y Escribe Código Mejor

Los React Hooks son el presente y futuro de React. Dominarlos te convertirá en un desarrollador React más efectivo, permitiéndote escribir código más limpio, modular y fácil de mantener. La clave es practicar y comprender los conceptos fundamentales: useState para estado, useEffect para efectos, y crear custom hooks para lógica reutilizable.

Comienza ahora mismo a refactorizar tus componentes de clase a hooks y verás la diferencia en la calidad de tu código.

Escrito por Andrés Saumet - Especialista en React y JavaScript moderno con más de 5 años de experiencia.

Andres Saumet

Sobre el autor

Andres Saumet

Desarrollador Web & Móvil Full Stack · Colombia

Hay mil desarrolladores que pueden hacer que algo funcione. Yo me obsesiono con hacer que funcione y genere dinero.

Soy Andres Saumet, desarrollador Web y Móvil con foco en rentabilidad. Trabajo con startups, emprendedores y empresas que ya tienen una visión clara y necesitan a alguien que la convierta en un producto digital real — uno que los usuarios quieran usar y que el negocio quiera escalar.

Domino React, Next.js, React Native y Node.js. Pero más allá del stack, entiendo cómo piensan los usuarios, cómo fluye un negocio y qué decisiones técnicas impactan directamente en los ingresos.

Cada línea de código que escribo tiene un propósito: que tu producto web o móvil sea más rápido, más usable y más rentable.

¿Tienes un producto que necesita crecer? Construyámoslo juntos.

Compartir:
Volver al Blog

Todos los derechos reservados Andres Saumet 2026 ©