useWidth, useHeight ? Custom hook para obtener tamaño de la pantalla.
Published: 2021-11-08 17:31:21

## Introducción

En este post te explicare como crear un custom hook que te permita obtener los valores del ancho y alto de la pantalla. 
Un ejemplo de muchos para usar este custom hook, puede ser para ocultar un elemento si la pantalla tiene poco espacio.

Sin mas preambulo, vamos a darle !

## Empecemos 👨🏻‍💻 ☕️ 

Lo primero que necesitamos es crear nuestro custom hook, yo lo hare en una carpeta llamada hooks y dentro de ella creare el archivo useScreenSize.js

```
 src /
 |  hooks /
 |  |  useScreenSize.js
 app.js
 index.js
 styles.css
```

Vamos a importar los hooks de react: useState & useEffect,
a crear nuestra function que exportaremos y agregaremos dos estados para el alto y el ancho

```javascript
import { useState, useEffect } from "react";

const useScreenSize = () => {
  const [width, setWidth] = useState();
  const [height, setHeight] = useState();
  
  return { height, width }
}

export default useScreenSize;
```

Yo he decidido retornar los valores en un objeto, sin embargo puedes hacerlo en un array o de la manera que gustes, pero para mí es mas limpio y claro en un objeto. 

Los estados width y height nos darán su tamaño respectivo de pixeles en forma de numero (number). Para obtener estos valores necesitamos llamar al objeto window del DOM. Así que agregaremos este valor inicial en nuestros estados de inicio para el alto y ancho cada vez que usemos nuestro customHook

```javascript
  const [width, setWidth] = useState(window.innerWidth);
  const [height, setHeight] = useState(window.innerHeight);
```

Ahora necesitamos decirle a nuestro customHook que actualice los valores cada vez que el usuario cambie el tamaño de la ventana, así que necesitamos una función que nos diga que se actualicen estos valores. 

```javascript
  const handleResize = () => {
    setWidth(window.innerWidth);
    setHeight(window.innerHeight);
  };
```

Esta función por sí sola no obtendrá los valores cada vez que se cambie el tamaño de la ventana, necesitamos del hook useEffect para cambiar el estado (valores) del ancho y alto.
Agreguemos el hook useEffect con lo siguiente:

```javascript
  useEffect(() => {
    window.addEventListener("resize", handleResize);
  }, []);
```

Lo que se esta haciendo aquí, es que estamos agregando un listener que va a escuchar cada vez que se cambie el tamaño de la ventana, y como puedes ver le estamos agregando en el segundo parámetro la función que debe hacer, que para nuestro caso es simplemente actualizar el valor del alto y ancho. 

Hasta este punto nuestro custom hook ya funciona y podemos obtener los valores del ancho y alto cada vez que se cambie el tamaño de la ventana y el código va así:

```javascript
import { useState, useEffect } from "react";

const useScreenSize = () => {
  const [width, setWidth] = useState();
  const [height, setHeight] = useState();
  
  useEffect(() => {
    setWidth(window.innerWidth);
    setHeight(window.innerHeight);

    window.addEventListener("resize", handleResize);
  }, []);
  
  return { height, width }
}

export default useScreenSize;
```
Si dejamos el hook de esta manera, podemos provocar que crahsee nuestra app y no solo nuestra app, si no hacer lenta la computadora.

**Si te preguntas por qué ? Y no sabes un, dejame explicarte:**

Nuestro hook funciona de manera correcta, sin embargo, el listener seguirá actualizando los valores en todas las vistas/paginas de la aplicación en todo momento, lo que ocasiona que se consuma mucha memoria de la computadora. Para ello necesitamos quitar el listener una vez que dejemos de usar el hook y no tenerlo siempre activo. Así que lo único que tenemos que hacer es pararlo en nuestro useEffect: 

```javascript
  useEffect(() => {
    setWidth(window.innerWidth);
    setHeight(window.innerHeight);

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

Con esto evitamos que creashee nuestra maquina y evitamos el consumo de memoria. Cada vez que dejemos de usar nuestro hook en un componente/pagina o donde lo implementemos, eliminamos el listener y la función que tiene que dejar de hacer. 

Este seria nuestro código final: 

```javascript
import { useState, useEffect } from "react";

const useScreenSize = () => {
  const [width, setWidth] = useState(window.innerWidth);
  const [height, setHeight] = useState(window.innerHeight);

  useEffect(() => {
    window.addEventListener("resize", handleResize);

    return () => {
      window.removeEventListener("resize", handleResize);
    };
  }, []);

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

  return { width, height };
};

export default useScreenSize;
```

Puedes ver mas a detalle este customHook en mi code sandbox:
https://codesandbox.io/s/usescreensize-ht3xw

Espero haber podido ayudarte y aportar algo de aprendizaje hoy a tu día.