4 Custom Hooks que todo desarrollador React debería conocer

2023, Abril 05
4 Custom Hooks que todo desarrollador React debería conocer

Muchas veces en nuestros proyectos de react nos encontramos con la necesidad de refactorizar nuestros componentes y extraer lógica que se repite en varios componentes, aqí es donde entran los custom hooks, y en este post te hablaré de los custom hooks que considero que debes saber si te dedicas al desarrollo web con React.

useForm

Empezando desde lo básico, este custom hook nos puede ayudar al manejo de nuestros formularios. Si bien es sabido que podemos instalar librerias como Formik o React Hook Form, en ocasiones no necesitamos una libreria tan robusta y podemos usar este custom hook para que nos facilite el manejo de los inputs de nuestros formularios.

    
import { useState } from 'react';

export const useForm = (initialState = {}) => {
  const [values, setValues] = useState(initialState);

  const reset = () => {
    setValues(initialState);
  };

  const handleInputChange = ({ target }) => {
    setValues({
      ...values,
      [target.name]: target.value,
    });
  };

  return [values, handleInputChange, reset];
};

  

useFetch

Muchas veces se comete el fallo de manejar toda la lógica de las peticiones dentro del componente, lo que hace que nuestro componente se vea sobrecargado y sea difícil de mantener. Ahora bien que tal si mantenemos toda la lógica de las peticiones en un custom hook y solo llamamos a ese hook en nuestro componente, de esta manera nuestro componente se verá mucho más limpio y fácil de mantener.

    
import { useEffect, useRef, useState } from 'react';

export const useFetch = (url) => {
  const isMounted = useRef(true);
  const [state, setState] = useState({ data: null, loading: true, error: null });

  useEffect(() => {
    return () => {
      isMounted.current = false;
    };
  }, []);

  useEffect(() => {
    setState({ data: null, loading: true, error: null });
    fetch(url)
      .then((resp) => resp.json())
      .then((data) => {
        if (isMounted.current) {
          setState({
            loading: false,
            error: null,
            data,
          });
        }
      });
  }, [url]);

  return state;
};

  

Si estamos utilizando typescript, este custom hook bien podría sacar ventaja de los genéricos para mejorar la satisfacción del tipado.

    
import { useEffect, useRef, useState } from 'react';

export const useFetch = <T>(url: string) => {
  const isMounted = useRef(true);
  const [state, setState] = useState<{ data: T | null; loading: boolean; error: null }>({
    data: null,
    loading: true,
    error: null,
  });

  useEffect(() => {
    return () => {
      isMounted.current = false;
    };
  }, []);

  useEffect(() => {
    setState({ data: null, loading: true, error: null });
    fetch(url)
      .then((resp) => resp.json())
      .then((data) => {
        if (isMounted.current) {
          setState({
            loading: false,
            error: null,
            data,
          });
        }
      });
  }, [url]);

  return state;
};

  

useDebounce

Imagina que tienes un input de búsqueda y quieres que se haga la petición a la API solo cuando el usuario deje de escribir, disparar un evento cada vez que el usuario escribe en el input puede ser costoso y no es necesario, por lo que podemos usar este custom hook para que se dispare el evento en un tiempo determinado o cuando el usuario deje de escribir.

    
import { useEffect, useState } from 'react';

export const useDebounce = (value, delay = 300) => {
  const [debouncedValue, setDebouncedValue] = useState(value);

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

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

  return {
    debouncedValue,
  };
};

  

useNearScreen

Apoyandonos de la api de Intersection Observer podemos crear un custom hook que nos permita saber si un elemento se encuentra en la pantalla o no, esto puede ser muy útil para hacer lazy loading de imágenes, para mostrar un componente solo cuando el usuario lo vea e incluso el famoso infinite scroll.

    
import { useEffect, useRef, useState } from 'react';

export const useNearScreen = (externalRef, options = {}, once = false) => {
  const [isVisible, setIsVisible] = useState(false);

  useEffect(() => {
    if(!externalRef.current) return;
    const onChange = ([{ isIntersecting }], observer) => {
      if (isIntersecting) {
        setIsVisible(true);
        once && observer.disconnect();
      }else {
        !once && setIsVisible(false);
      }
    }
    const observer = new IntersectionObserver(onChange, options);
    observer.observe(externalRef.current);
    return () => observer.disconnect();
  }, [externalRef]);

  return { isVisible }
};

  

Espero que estos hooks te sean de utilidad 🧑‍💻, y si ya los conocías, espero al menos que te haya servido para recordarlos y que los pongas en práctica en tus proyectos de react😁