• +34 685 967 885
  • +34 695 898 191
  • antgarprats@gmail.com
  • Antonio García Prats

patrones avanzados en react hooks

Patrones avanzados de react hooks

Los React Hooks son una de las características más potentes y versátiles de React, introducidas a partir de la versión 16.8. Permiten a los desarrolladores escribir código funcional y reutilizable al trabajar con estados, efectos secundarios y otras funcionalidades sin necesidad de usar clases. En este artículo, exploraremos desde los conceptos básicos hasta los patrones avanzados de react hooks que puedes aplicar para llevar tus habilidades con React Hooks al siguiente nivel.

¿Qué es un React Hook y para qué sirve?

Un React Hook es una función especial de React que permite «enganchar» («hook into») características fundamentales de React, como el estado y el ciclo de vida, dentro de componentes funcionales.

Ejemplos Clásicos de Hooks:

-useState: Maneja el estado en un componente funcional.

useEffect: Gestiona efectos secundarios, como llamadas a APIs o suscripciones.

useContext: Accede al contexto de React sin necesidad de envolver componentes.

Estos Hooks básicos transformaron la manera en que los desarrolladores trabajan con React, pero su – fuerza radica en la posibilidad de crear Hooks personalizados (custom hooks).

¿Cómo crear un React Hook personalizado?

Un Hook personalizado es una función de JavaScript que sigue la convención de nombrarse con el prefijo use y que puede encapsular lógica reutilizable. Su propósito es mejorar la organización del código y evitar redundancias.

Estructura típica de un Hook personalizado:

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);
                if (!response.ok) throw new Error('Network response was not ok');
                const result = await response.json();
                setData(result);
            } catch (err) {
                setError(err.message);
            } finally {
                setLoading(false);
            }
        };

        fetchData();
    }, [url]);

    return { data, loading, error };
}

export default useFetch;

Uso del Hook personalizado:

import React from 'react';
import useFetch from './useFetch';

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

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

    return (
        <div>
            <h1>Data:</h1>
            <pre>{JSON.stringify(data, null, 2)}</pre>
        </div>
    );
}

export default App;

Este es un ejemplo clásico de cómo un Hook personalizado encapsula una lógica común (realizar una solicitud HTTP) y la hace reutilizable en cualquier componente.

Patrones Avanzados de React Hooks

1. Control de Estado Complejo con useReducer

Cuando el estado es más complejo que unas pocas variables, useReducer es una alternativa poderosa a useState.

Ejemplo:
import { useReducer } from 'react';

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:
            throw new Error('Unknown action type');
    }
}

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

    return (
        <div>
            <p>Count: {state.count}</p>
            <button onClick={() => dispatch({ type: 'increment' })}>+</button>
            <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
        </div>
    );
}

export default Counter;

Este patrón es especialmente útil para formularios o estados con varias propiedades interdependientes.

2. Composición de Hooks

Puedes combinar varios Hooks personalizados para crear soluciones aún más potentes y especializadas.

Ejemplo:
function useAuth() {
    const [user, setUser] = useState(null);

    useEffect(() => {
        const fetchUser = async () => {
            const data = await fakeAuthAPI(); // Simulación de una API de autenticación
            setUser(data);
        };

        fetchUser();
    }, []);

    return user;
}

function useUserData() {
    const user = useAuth();
    const { data, loading } = useFetch(`/api/user/${user?.id}`);

    return { user, data, loading };
}

function Profile() {
    const { user, data, loading } = useUserData();

    if (loading) return <p>Loading user data...</p>;
    return (
        <div>
            <h1>Welcome, {user.name}!</h1>
            <p>Your data: {JSON.stringify(data)}</p>
        </div>
    );
}

Este patrón permite construir Hooks módulos que se apoyan entre sí.

3. Patrón de Re-Renderizado Controlado

Cuando el rendimiento es una preocupación, puedes usar useRef y useCallback para evitar renders innecesarios.

Ejemplo:
import { useState, useCallback } from 'react';

function ExpensiveComponent({ compute }) {
    console.log('Rendering ExpensiveComponent');
    return <p>Computed Value: {compute()}</p>;
}

function App() {
    const [count, setCount] = useState(0);

    const compute = useCallback(() => {
        return count * 2;
    }, [count]);

    return (
        <div>
            <button onClick={() => setCount(count + 1)}>Increment</button>
            <ExpensiveComponent compute={compute} />
        </div>
    );
}

export default App;

Con useCallback, evitamos que la función compute se regenere en cada render, lo que optimiza el rendimiento.

4. Hooks Controlados por Eventos Personalizados

Los Hooks pueden escuchar eventos personalizados o del navegador.

Ejemplo:
import { useState, useEffect } from 'react';

function useWindowSize() {
    const [size, setSize] = useState({ width: window.innerWidth, height: window.innerHeight });

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

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

    return size;
}

function App() {
    const { width, height } = useWindowSize();

    return (
        <div>
            <p>Window size: {width} x {height}</p>
        </div>
    );
}

export default App;

Aplicaciones Habituales de React Hooks

Gestor de estado: Simplifica el manejo de estados locales o globales.

Integración con APIs: Hooks como useFetch encapsulan lógica de solicitudes.

Optimizaciones: Reducen renders innecesarios con useMemo y useCallback.

Eventos del navegador: Escucha y maneja eventos, como cambios en el tamaño de la ventana o pulsaciones del teclado.

Desarrollo de librerías: Hooks personalizados permiten crear herramientas especializadas para proyectos.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *