Intro a Custom Hooks
Tags: javascript, hook, react, beginners
Published: 2023-02-28 19:11:04

Como principiantes en React, hay mucho que abarcar y aprender. Un tema importante es Custom Hooks. Que si bien usamos hooks todo el tiempo, poder crear los nuestros nos va a dar un punto más a la hora de aplicar buenas prácticas y limpiar nuestro código.

Ese enfoque vamos a tomar, refactorizar nuestro código creando hooks personalizados.

---

## Empecemos por las bases

Todo en react básicamente son funciones, la clave está en cómo se escriben. React las reconoce bajo esta norma:

```jsx
// Componentes | Deben empezar con mayúscula
const MyComponent = (props) => { ...
```

```jsx
// Funciones normales | Siempre empiezan con minúsculas
const inputHandler = (e) => { ...
```

```jsx
// Hooks | Siempre empiezan con use
const [value, setValue] = useState(); // 
```

---

## Regla importantísima

El problema que nos surge siempre, es que cuando queremos usar hooks de react en nuestras funciones normales, [la regla de hooks](https://reactjs.org/docs/hooks-rules.html) nos va a advertir que los hooks solo pueden usarse dentro de componentes de react o de otros hooks.

## Y para qué usaríamos un custom hook?

Vamos a limpiar este componente simple:

```jsx
import React, { useState } from 'react';

const ModeSwitcher = () => { // Componente
  const [darkMode, setDarkMode] = useState(false); // Hook
  const [readMode, setReadMode] = useState(false);

  const toggleDarkMode = () => { // Función
    setDarkMode(!darkMode);
  };

  const toggleReadMode = () => {
    setReadMode(!readMode);
  };

  return (
    <div>
      <button onClick={toggleDarkMode}>
        {darkMode ? 'Light Mode' : 'Dark Mode'}
      </button>

      <button onClick={toggleReadMode}>
        {readMode ? 'Read Mode' : 'Normal Mode'}
      </button>
    </div>
  );
};
```

En este código simple, tenemos dos botones ficticios que simulan un modo "activado/desactivado" para un estado en la aplicación.

Esto es simple y entendible en cómo funciona. Pero si quisiéramos agregar más estados, pecaríamos con la repetición de los useState y las funciones de toggle.

Como refactorización simple, nos vamos a llevar a un hook la lógica de activación y desactivación de un solo switch:

```jsx
const useSwitch = () => { // empieza con 'use'
  const [switchMode, setSwitchMode] = useState(false);

  const toggleSwitchMode = () => {
    setSwitchMode(!switchMode);
  }

  return [switchMode, toggleSwitchMode];
}
```

> Al ser una función normal, pero empezarla con `use`, le estamos diciendo a react que es un hook, y por lo tanto nos va a permitir usar otro hook en su interior (useState en este caso).

Esta función realmente puede convivir dentro del mismo componente, pero lo usual es importarlo desde otro archivo, a este hook le haríamos la siguiente modificación en ese caso:

```jsx 
// useSwitch.js
import React, { useState } from 'react';

export default function useSwitch() { //...

```

---

## Usando el hook

Ahora, simplemente vamos a reemplazar el código interno que teníamos de nuestra app para utilizar nuestro hook, incluso en los dos casos a la vez:

```jsx
import useSwitch from './useSwitch';

const ModeSwitcher = () => {
  const [darkMode, toggleDarkMode] = useSwitch(); // Nuestro hook
  const [readMode, toggleReadMode] = useSwitch();

  return (
    <div>
      <button onClick={toggleDarkMode}>
        {darkMode ? 'Light Mode' : 'Dark Mode'}
      </button>

      <button onClick={toggleReadMode}>
        {readMode ? 'Read Mode' : 'Normal Mode'}
      </button>
    </div>
  );
}
```

El detalle interesante es que podemos darle el nombre que queramos a cada state y su función para hacer toogle para diferenciarlos:

```jsx
const [active, switchActive] = useSwitch(); // Por ej.
```

Para entender lo anterior, leé sobre [desestructuración de arrays](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment).

## En resumen

Por un lado, notar que eliminamos el `useState` de nuestro componente principal. Lo cual es un buen refactor, ya que si tenés hooks típicos de react en tus componentes (useState o useEffect), es una buena señal de que podés llevártelos a un custom hook para limpiar el código y refactorizar de manera más profesional tu código.

---

Si te gustó este post y te gustaría que haga otros custom hooks para profundizar o poder usar otros ejemplo, dejámelo en los comentarios y exploramos.

Gracias!