Introducción a React Hooks para principiantes: Fundamentos y uso

Go to Homepage

Una introducción a React Hooks

Si eres un desarrollador de front-end que utiliza React para programación del lado del cliente en desarrollo web, quizás hayas oído hablar de los React Hooks. Los Hooks son una nueva adición a React desde la versión 16.8.0 que permite la definición de estados y el uso de ciclo de vida de componentes funcionales. Esencialmente, Hooks son funciones que puedes usar en un componente funcional en lugar de un componente de clase para trabajar con el estado y los ciclos vitales.

La principal ventaja de los Hooks es que permiten una manera más clara y sencilla de trabajar con el estado de los componentes. Los componentes de clase necesitan definir un constructor y el estado en el mismo, agregando complejidad al código y haciendo que sea más difícil de entender. Los componentes funcionales con Hooks permiten definir el estado de una manera más sencilla y legible.

Los Hooks también brindan una forma más concisa de escribir ciclos de vida, lo que permite una mayor legibilidad del código. Los ciclos de vida son esenciales para la interacción efectiva con los componentes React, y la capacidad de escribir ciclos de vida de manera más clara y sencilla puede hacer que el desarrollo de software en React sea más eficiente.

Los React Hooks han sido bien recibidos por toda la comunidad de desarrollo web, y muchos expertos en JavaScript los han adoptado como la forma preferida de trabajar con el estado y los ciclos de vida en React. En general, los Hooks son una herramienta poderosa para simplificar la forma en que los desarrolladores trabajan con React y ofrecen una experiencia de desarrollo de software más fluida.

Los React Hooks son una nueva adición emocionante a React que permite a los desarrolladores de front-end trabajar con el estado y los ciclos de vida de componentes de manera sencilla y concisa. Si aún no has utilizado los Hooks, te recomendamos que los pruebes en tu próximo proyecto de desarrollo web en React. Los Hooks son una herramienta poderosa para simplificar tu código y pueden hacer que la programación en React sea más fluida.

Cómo utilizar useState para manejar el estado

En la programación de desarrollo web React es una de las bibliotecas de JavaScript más populares utilizadas en el Front-End de sitios web. Los Hooks son una característica agregada a React desde la versión 16.8 que permiten administrar el estado y los efectos en componentes funcionales. En este tutorial, presentaremos uno de los hooks más comunes: useState.

useState es un Hook que permite definir estados locales en los componentes funcionales sin la necesidad de utilizar clases. El uso de useState y otros Hooks hace la programación más legible y fácil de mantener. Para usar useState, primero debemos importarlo:

import React, { useState } from "react";

El ejemplo más simple es crear un estado booleano:

const [isActive, setIsActive] = useState(false);

En este caso la variable isActive es el estado que se guardará y setIsActive es una función que se encarga de actualizar el estado. Cuando useState se inicializa, recibe un valor inicial que en este caso es false. Luego podemos usar isActive en nuestro código como cualquier otra variable.

Un ejemplo más completo es una lista de colorees. Supongamos que queremos mostrar una lista de colores y permitir al usuario seleccionar el color deseado. Primero definimos los estados que necesitaremos:

const [colors, setColors] = useState([
    { name: "Rojo", selected: false },
    { name: "Azul", selected: false },
    { name: "Verde", selected: false },
]);

Aquí estamos inicializando una variable llamada colors que es un arreglo con tres elementos objetos. Cada objeto contiene el nombre del color y un estado selected inicializado en false. Ahora podemos usar esta lista para mostrar los colores en nuestro componente:

{
    colors.map((color, index) => (
        <div key={index} style={{ backgroundColor: color.name }}>
            <label>
                <input
                    type="checkbox"
                    checked={color.selected}
                    onChange={() =>
                        setColors([
                            ...colors.slice(0, index),
                            { ...color, selected: !color.selected },
                            ...colors.slice(index + 1),
                        ])
                    }
                />
                {color.name}
            </label>
        </div>
    ));
}

Aquí estamos utilizando la función map() que nos permite generar dinámicamente componentes en función de nuestra lista de colores. Para cada color, creamos un checkbox que desencadena una actualización del estado cuando se hace clic para cambiar el valor de su propiedad selected.

useState es una de las características más importantes cuando se trata de programación en React. Permite definir estados locales en componentes funcionales sin tener que utilizar clases. Al usar useState, el código es más fácil de seguir y mantener. Se pueden utilizar los estados para almacenar información actualizada y dinámica en nuestros componentes. Y los efectos y las actualizaciones del estado se pueden controlar y actualizar de manera efectiva utilizando funciones como useEffect. Esta es solo la punta del iceberg, ¡así que sigue adelante y aprende más sobre los hooks!

Implementando useEffect para efectos secundarios

Una gran ventaja de los React Hooks es la capacidad de manejar efectos secundarios en el desarrollo web de manera más clara y sencilla. El useEffect es uno de los React Hooks más utilizados para ejecutar código secundario después de renderizar un componente.

En este tutorial, explicaremos cómo usar useEffect en un componente y cómo manejar diferentes efectos secundarios. La sintaxis básica de useEffect es la siguiente:

useEffect(() => {
    // Efecto secundario
}, [dependencias]);

El primer parámetro es una función que contiene el código que se ejecutará después de que el componente se haya montado o actualizado. El segundo parámetro es un array de dependencias opcionales que, si cambian, activarán nuevamente la función.

Por ejemplo, si queremos ejecutar un efecto secundario solo cuando una prop específica cambie podemos hacer esto:

useEffect(() => {
    // Efecto secundario
}, [props.nombreProp]);

Pero si no queremos depender de ninguna prop o estado, podemos pasar un array vacío como segundo parámetro. De esta forma, la función solo se ejecutará después de que el componente se monte.

useEffect(() => {
    // Efecto secundario
}, []);

El useEffect también tiene la capacidad de devolver una función de limpieza, que se utilizará para cancelar el efecto secundario o hacer alguna limpieza antes de que el componente se desmonte.

Por ejemplo, si estamos suscribiéndonos a un evento del DOM a través de addEventListener debemos limpiar la suscripción antes de que el componente se desmonte.

useEffect(() => {
    const handleClick = () => {
        // código del evento
    };
    document.addEventListener("click", handleClick);
    return () => {
        document.removeEventListener("click", handleClick);
    };
}, []);

El código dentro de la función de limpieza se ejecutará solo cuando el componente se desmonte. En resumen, useEffect es una herramienta muy poderosa para manejar efectos secundarios en React Hooks.

useEffect es una de las características más importantes de React Hooks para el manejo de efectos secundarios en el desarrollo web. Esta herramienta nos permite ejecutar código secundario después de que un componente se haya montado o actualizado y también se encarga de limpiar ese código antes de que el componente se desmonte. Con esto podemos mantener código más limpio y fácil de entender. Recomendamos seguir practicando en la implementación de esta herramienta en tus proyectos.

Usando useContext para la gestión del contexto

En el desarrollo web, el uso de React es cada vez más común ya que este framework de Front-End permite una forma más fácil y eficiente de construir interfaces de usuario. Con la incorporación de React Hooks en la última versión de React, es posible utilizar técnicas de programación funcional para el manejo de estados en nuestras aplicaciones.

Uno de estos hooks es useContext, el cual nos permite la gestión del contexto en nuestra aplicación, lo que significa que podemos pasar datos de un componente a otro sin necesidad de utilizar props. En lugar de esto, podemos utilizar un objeto especial llamado Context, el cual se encarga de almacenar estos datos.

Para utilizar useContext, primero debemos crear un contexto utilizando la función createContext de React. Este contexto puede contener cualquier tipo de datos que necesitemos compartir en nuestra aplicación, como por ejemplo el estado global.

import { createContext } from "react";

const GlobalContext = createContext(null);

Una vez creado el contexto, es necesario envolver todos los componentes que necesiten de acceso al mismo utilizando el componente Provider que se exporta junto al objeto GlobalContext.

import React from "react";
import { GlobalContext } from "./GlobalContext";

function App() {
    const [globalState, setGlobalState] = useState({});

    return (
        <GlobalContext.Provider value={globalState}>
            <Navbar />
            <BuyButton />
        </GlobalContext.Provider>
    );
}

En este ejemplo, el componente BuyButton necesita acceder al estado global almacenado en el contexto. Para ello, debemos utilizar la función useContext que nos permite acceder al contexto de forma sencilla.

import React, { useContext } from "react";
import { GlobalContext } from "./GlobalContext";

function BuyButton() {
    const globalState = useContext(GlobalContext);

    function handleClick() {
        console.log("El estado global es:", globalState);
    }

    return <button onClick={handleClick}>Comprar</button>;
}

En este caso, la función useContext nos devuelve el estado global almacenado en el contexto, el cual podemos utilizar en nuestro componente. Además, cada vez que el estado global cambie, React se encargará de llamar a los componentes que han utilizado useContext para que se actualicen con la nueva información.

El uso de useContext en React Hooks nos permite una forma más fácil y eficiente de manejar el estado global en nuestra aplicación. Además, nos permite evitar la incomodidad y las limitaciones que suponen las props para el paso de información entre componentes. Es importante tener en cuenta que el uso de useContext no es la única forma de manejar el contexto en React, pero sí es una opción muy recomendable y útil en numerosos casos.

La importancia de useMemo y useCallback para optimización

La programación en React, y en general en el front-end, puede ser complicada debido a la cantidad de actualizaciones que se hacen en la interfaz de usuario. No solo esto, sino que también en los últimos años ha habido una tendencia hacia el desarrollo de software que se actualiza más frecuentemente. como los desarrolladores web, es importante para nosotros encontrar formas de optimizar nuestro código y minimizar el tiempo necesario para cargar la aplicación.

Es aquí donde las Hooks de React, como useMemo y useCallback, se convierten en herramientas importantes para el desarrollo de software moderno. Como se menciona en el título, esta es una introducción para principiantes, pero en resumen, los Hooks son funciones que nos permiten usar el estado y otras características de React sin escribir clases.

Entonces, ¿cómo es que useMemo y useCallback se vuelven importantes para nosotros? Pues bien, useMemo es una función que nos permite “memorizar” valores y solo actualizarlos cuando sea necesario. Lo que esto significa, es que cualquier valor que dependa de algún estado o datos que se hayan actualizado previamente, no necesariamente se tiene que volver a calcular cada vez que haya una actualización. De esta manera, se mejora la eficiencia de la aplicación.

Por su parte, useCallback se utiliza para evitar la recreación innecesaria de funciones onChange y onClick cuando no es necesario. Al utilizar useCallback, se asegura que la función solo se vuelva a crear cuando los valores de entrada que se le pasan cambian. Esto ayuda a reducir la sobrecarga en el navegador. Este fue también uno de los desafíos de los hooks más tempranos, pero useCallback lo soluciona de manera efectiva.

En cuanto a su uso, useCallback es útil cuando se manejan funciones que deben ser reutilizadas en la aplicación. Si tenemos una función que simplemente devuelve double el numero pasado, useCallback puede optimizar el rendimiento al proteger la recreación de la función cada vez que se renderiza el componente.

Con useMemo, podemos hacer lo mismo pero para calcular valores costosos. Supongamos que tenemos una lista de 1000 elementos y al renderizar la vista, queremos calcular la suma de los cuadrados para todos los elementos. Al utilizar useMemo, podemos “memorizar” el resultado y solo actualizarlo cuando se hayan añadido valores a la lista o se hayan eliminado. De esta manera, podemos seguir haciendo cálculos complejos sin que la interfaz de usuario se vuelva lenta.

En el desarrollo de software moderno, la optimización es clave y los Hooks de React son herramientas que nos permiten hacerlo. Con useMemo y useCallback, podemos optimizar el rendimiento de nuestra aplicación y hacer que responda más rápidamente. Si eres nuevo en los Hooks, ¡te recomendamos que eches un vistazo a la documentación y comiences a utilizarlas en tu aplicación!

Creando nuestros propios hooks personalizados

La belleza de React Hooks es la capacidad de reutilizar código de manera eficiente, y crear nuestros propios hooks personalizados es una excelente manera de llevar la capacidad de reutilización al siguiente nivel.

Para crear un hook personalizado, debemos seguir algunas convenciones simples de programación. Primero, nuestro hook debe tener un nombre que comience con use para indicar claramente que estamos utilizando un hook.

Una vez que tengamos un nombre claro, podemos codificar nuestro hook dentro de una función y exportarlo. JavaScript nos proporciona una gran capacidad para reutilizar y modularizar código, y la creación de hooks personalizados nos ayuda a llevar al límite esa capacidad.

Por ejemplo, digamos que queremos crear un hook que calcule la suma de dos números dados. Podríamos llamarlo useSum y definirlo así:

import { useState } from "react";

function useSum(a, b) {
    const [sum, setSum] = useState(a + b);

    function calculateSum() {
        setSum(a + b);
    }

    return [sum, calculateSum];
}

export default useSum;

Este hook useSum toma dos argumentos, a y b, y devuelve un arreglo que contiene el valor de la suma calculada y una función que se puede llamar para actualizar el valor de la suma.

Podemos llamar a este hook useSum en cualquier lugar de nuestro código, sin tener que preocuparnos por cómo se calcula la suma. Esto nos ayuda a mantener nuestro código modular, legible y fácil de mantener.

La creación de hooks personalizados es una técnica fundamental y útil para cualquier desarrollador de React que busque mejorar su capacidad de reutilización y modularización del código en sus proyectos de desarrollo web y desarrollo de software en general. Con un poco de práctica, puede crear sus propios hooks personalizados que proporcionen funciones útiles y eficientes en sus proyectos de front-end y programación en general.

Cómo solucionar problemas comunes con los hooks

Los React Hooks son una herramienta útil para solucionar problemas comunes en la programación de React. A continuación, se presentará una lista de problemas comunes y cómo solucionarlos mediante el uso de los hooks:

Compartir lógica entre componentes.

Utilizar el hook useMemo para definir valores costosos computacionalmente y garantizar que no se recompute innecesariamente. También se puede utilizar el hook useCallback para definir callbacks que se mantienen igual entre renderizaciones. Ambos hooks permiten optimizar el rendimiento de nuestra aplicación.

Manejar estados complejos.

Utilizar el hook useState para manejar estados en componentes funcionales. Los estados pueden ser objetos o arreglos complejos, permitiendo actualizar valores en específico sin cambiar otros valores.

Manejar el ciclo de vida de los componentes.

Utilizar el hook useEffect para manejar ciclos de vida como montaje, actualización y desmontaje de componentes. Este hook permitirá ejecutar código en momentos específicos del ciclo de vida, como configurar timers antes de que el componente monte, o limpiar efectos después de que el componente se desmonte.

Acceder a valores de contexto en componentes hijos.

Utilizar el hook useContext para acceder a valores de contexto definidos en componentes padres. Este hook permitirá que los componentes hijos tengan acceso a valores importantes en diferentes niveles.

Optimizar el rendimiento de una aplicación.

Utilizar los hooks mencionados anteriormente para optimizar el rendimiento de la aplicación. También se puede utilizar el hook useReducer para manejar estados complejos en vez de utilizar el hook useState. Este hook permite manejar estados de una forma más eficiente, ayudando a reducir el tiempo de renderizado.

Los hooks proporcionan a los desarrolladores de front-end una herramienta poderosa para solucionar problemas en la programación de componentes de React. Los hooks nos permiten manejar estados complejos, acceder a valores importantes en diferentes niveles, manejar ciclos de vida de forma más eficiente y optimizar el rendimiento de nuestra aplicación. Si eres nuevo en los hooks, te recomendamos revisar tutoriales en línea como el de la documentación de React o el tutorial en línea de Javascript para familiarizarse con su uso.

import React, { useState, useMemo, useCallback } from "react";

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

    const onButtonClick = useCallback(() => {
        setCount(count + 1);
    }, [count]);

    const expensiveValue = useMemo(() => {
        let result = count;
        for (let i = 0; i < 1000000000; i++) {
            result = result + i;
        }
        return result;
    }, [count]);

    useEffect(() => {
        const timerId = setTimeout(() => {
            setCount(count + 1);
        }, 1000);
        return () => {
            clearTimeout(timerId);
        };
    }, [count]);

    return (
        <div>
            <p>Count: {count}</p>
            <p>Expensive value: {expensiveValue}</p>
            <button onClick={onButtonClick}>Increment count</button>
        </div>
    );
}

export default MyComponent;

Utilizando useRef para interactuar con DOM

La idea de utilizar React es hacer que el desarrollo de software web sea más fácil y más rápido. La programación front-end siempre ha sido compleja porque hay muchas cosas que están cambiando con mucha frecuencia. Ahí es donde React entra en juego, ya que organiza la complejidad y proporciona una manera práctica de trabajar con ella.

React Hooks es una forma relativamente nueva de trabajar con React. Antes de que se introdujeran los Hooks, los desarrolladores tenían que trabajar con clases. Ahora, con los hooks, pueden crear componentes sin la necesidad de escribir una clase. Los hooks son funciones especiales que “enganchan” nuestro código a los componentes de React.

Una función de hook útil es useRef. useRef nos da la posibilidad de referenciar a un elemento en el documento y utilizarlo posteriormente en nuestra lógica. Recuerda que en React, todo es un componente, incluso un botón. En lugar de escribir funciones enormes para realizar acciones cada vez que hacemos clic en un botón, podemos utilizar useRef para hacer referencia al botón en nuestra lógica y realizar acciones con él.

Supongamos que tenemos un contador en nuestro componente que queremos actualizar cada vez que se haga clic en un botón. Normalmente, tendríamos que hacer referencia al botón por su identificador y luego llamar a una función para actualizar el contador. Con useRef, simplemente referenciamos al botón en nuestro componente. Aquí hay un ejemplo de cómo se vería esto en código:

import React, { useRef, useState } from "react";

function Contador() {
    const [contador, setContador] = useState(0);
    const boton = useRef(null);

    const handleClick = () => {
        setContador(contador + 1);
        boton.current.disabled = true;
    };

    return (
        <div>
            <h2>Contador: {contador}</h2>
            <button ref={boton} onClick={handleClick}>
                Aumentar contador
            </button>
        </div>
    );
}

En este ejemplo, creamos una función Contador que utiliza useRef para referenciar el botón y una función de estado que actualiza el contador cada vez que se hace clic en el botón.

Si bien este es un ejemplo simple, se puede ver cómo useRef puede ser un recurso valioso en la lógica de los componentes de React. Incluso puedes utilizarlo para referenciar a múltiples elementos del DOM.

useRef es una función esencial de los React Hooks que nos permite interactuar con el DOM y hacer referencia a elementos en nuestro código. Al utilizar esta función, podemos reducir la cantidad de líneas de código que escribimos, haciéndolo mucho más legible y fácil de seguir. Además, useRef proporciona una mejor forma de organizar y manejar la complejidad de nuestro código, lo que hace que la programación con React sea más asequible y fácil de entender.

Escribiendo pruebas con hooks en Jest

En la programación de front-end, es importante entender todo sobre React Hooks, una función incorporada en el paquete de React que permite el uso de conceptos de programación de una manera más simple. Utilizar React Hooks hace que el código sea más fácil de entender y mantener a largo plazo.

Una de las cosas que debemos tener en cuenta al escribir código con hooks es que las pruebas son cruciales para garantizar su correcto funcionamiento. En este tutorial utilizaremos Jest, una biblioteca de pruebas de JavaScript que es ampliamente utilizada en el desarrollo de software.

Para escribir pruebas con React Hooks en Jest, en el primer paso debemos asegurarnos de instalar los paquetes necesarios. Podemos hacer esto utilizando npm o yarn. En este ejemplo, utilizaremos yarn.

Primero, recreamos nuestro proyecto utilizando create-react-app:

yarn create react-app prueba-hooks-jest
cd prueba-hooks-jest

Instalemos luego las siguientes dependencias:

yarn add react-test-renderer enzyme enzyme-adapter-react-16 enzyme-to-json

Ahora, estamos listos para escribir nuestras pruebas.

Primero, configuremos Jest en nuestro proyecto. Agreguemos lo siguiente en el archivo package.json:

"jest": {
    "setupFilesAfterEnv": [
        "<rootDir>/src/setupTests.js"
    ],
    "snapshotSerializers": [
        "enzyme-to-json/serializer"
    ],
    "moduleNameMapper": {
        "\\.(css|scss)$": "<rootDir>/__mocks__/styleMock.js"
    }
}

Después, creemos un archivo setupTests.js y agreguemos lo siguiente:

import { configure } from "enzyme";
import Adapter from "enzyme-adapter-react-16";

configure({ adapter: new Adapter() });

enzyme es una herramienta útil para hacer pruebas en React y enzyme-adapter-react-16 es el adaptador que usaremos para trabajar con React 16.

Es importante destacar que los hooks deben ser utilizados dentro de un componente React. Para ello, creemos un componente que contenga los hooks a ser probados.

import React, { useState } from "react";

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

    function handleOnClick() {
        setCount(count + 1);
    }

    return (
        <div>
            <h1>You clicked {count} times</h1>
            <button onClick={handleOnClick}>Click me</button>
        </div>
    );
}

export default Counter;

En el código anterior, se muestra un componente sencillo que tiene un botón que aumenta su contador cada vez que se hace clic en él.

Para probar este componente, debemos importar todo lo necesario en nuestro archivo de prueba.

import React from "react";
import { shallow } from "enzyme";
import Counter from "./Counter";

describe("Counter component", () => {
    const wrapper = shallow(<Counter />);

    it("should render correctly", () => {
        expect(wrapper.exists()).toBe(true);
    });

    it("should show initial state count as 0", () => {
        expect(wrapper.find("h1").text()).toEqual("You clicked 0 times");
    });

    it("should update when click event is fired", () => {
        wrapper.find("button").simulate("click");
        expect(wrapper.find("h1").text()).toEqual("You clicked 1 times");
    });
});

En este ejemplo de código, importamos el componente Counter y lo probamos utilizando shallow. Luego, realizamos tres pruebas distintas. En la primera prueba, verificamos si el componente se ha creado con éxito; en la segunda, comprobamos que el valor inicial sea cero, y en la tercera verificamos que el componente actualice su estado cuando hacemos clic en el botón.

Para escribir pruebas con hooks en React, se debe asegurar que las dependencias necesarias estén instaladas, configurar el entorno de pruebas y crear un componente de ejemplo. Después, se necesita importar todo lo necesario en el archivo de prueba y probar el componente utilizando shallow. Es importante destacar que las pruebas deben ser exhaustivas para garantizar que el componente funcione correctamente.

Explorando otros hooks útiles

Ya hemos hablado en detalle sobre los React Hooks en nuestro tutorial anterior, pero aunque hayamos cubierto mucho terreno, aún hay muchos otros hooks que merece la pena explorar. Vamos a echar un vistazo a algunos de estos hooks y cómo pueden ser útiles en el desarrollo web.

useReducer

Este hook es muy útil para manejar estado complejo. Nos permite modificar el estado de nuestra aplicación basándonos en acciones que nosotros definimos. Es muy similar al Redux, pero sin agregar ninguna dependencia adicional a nuestro proyecto.

useCallback

Este hook es usado para optimizar la performance. Nos permite crear una función y mantenerla en memoria, de modo que no se vuelva a crear cada vez que el componente se renderiza.

useMemo

Otro hook que nos ayuda a optimizar la performance. Nos permite cachear el resultado de una función y solo volver a calcularlo cuando cambia alguna de sus dependencias.

useContext

Este hook es muy útil para manejar el contexto global de nuestra aplicación. Nos permite pasar información de forma descendente a través de varios niveles de componentes sin tener que pasarlo a todos ellos como props.

useLayoutEffect

Este hook es similar al useEffect, pero se ejecuta sincrónicamente justo después de que el DOM se actualiza. Es muy útil para tareas que requieren de medidas del DOM, ya que nos permite acceder a ellas antes de que se renderice la pantalla.

useDebugValue

Este hook nos permite imprimir valores durante el debugging de nuestra aplicación. Es muy útil para imprimir valores complejos que nos ayuden a entender mejor el funcionamiento de nuestra app.

Hay muchos otros hooks disponibles para su uso en React, y cada uno de ellos tiene su propia utilidad. Es importante que se comprenda bien la documentación para que puedas usar estas herramientas lo mejor posible.

Los React Hooks son una herramienta muy poderosa para el desarrollo de software en el front-end. Si bien hay algunos aspectos de su uso que pueden ser un poco confusos al principio, con la práctica se pueden entender y utilizar con facilidad. Espero que este artículo haya sido útil para aprender más sobre los hooks y les haya inspirado para explorar otros hooks útiles en sus propios proyectos.

Otros Artículos