Implementando Dark Mode en Gatsby con Sass (2/2)
Tags: gatsby, react, sass, javascript
Published: 2020-01-29 20:15:59

---
title: Implementando Dark Mode en Gatsby con Sass (2/2)
published: true
description: En esta segunda parte veremos cómo crear un custom hook que contenga nuestra lógica para que el body tome color oscuro partir de un click.
tags: #gatsby #react #sass #javascript
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/82yuyycwptka4nsee7qu.png
---

| Implementando Dark Mode en Gatsby con Sass|
| -- |
| 1) [Integrando Sass en Gatsby](https://dev.to/jpgallegos1/implementando-dark-mode-en-gatsby-con-sass-1-2-7ec) |
| 2) [Implementando dark mode con un custom hook y Sass](https://#)|
Bienvenides a la segunda parte de la implementación del Dark Mode en Gatsby con Sass. En esta ocasión voy a arrancar definiendo variables y después crearemos un custom hook, el cual su lógica nos permitirá switchear entre fondo `light` o `dark`.

###Definiendo variables

Dentro de nuestra carpeta `sass` vamos a crear un archivo que voy a llamar `_vars.scss` y dentro de éste voy a nombrar cuatro variables:

Background:
- `$bgLight: rgb(243, 241, 241);`
- `$bgDark: rgb(32, 30, 30);`

Colores:

- `$green: rgb(40, 168, 40);`
- `$pink: rgb(243, 131, 237);`


**A saber**: nombrar los archivos con `_` al principio es una caracteristica de Sass y es conveniente que todos se nombren de esa forma menos el principal.

Lo siguiente que haremos es integrar nuestras variables al archivo principal `layout.scss` y para ello escribiremos la siguiente línea de código: `@import './vars';`. En este caso no hace falta que lleve extensión `.scss` dado que lo reconoce automáticamente. Para testear que todo funcione, en nuestro `layout.scss` escribiremos `body{ background: $bgDark }` y tendríamos que ver nuestro fondo negro en `localhost:8000`.

Finalmente a `layout.scss` le haré unas modificaciones, modificaré `pages/index.js` y agregaré `_index.scss` a mi carpeta de Sass. Debería quedar de la siguiente manera:


![Gatsby-Sass](https://dev-to-uploads.s3.amazonaws.com/i/0g6ci4p9k58tw8sxz6sm.png)

_En caso de tener un proyecto avanzado en Gatsby, asegúrate de que tu body reciba el `&.dark{ background: $bgDark }`_

### Creando el Custom Hook o Hook Personalizado

Como sabemos, en React tenemos distintos hooks como `useState`, `useEffect` o `useContext` que permiten distintas funcionalidades, pero algo realmente bueno de React es la posibilidad de crear nuestros propios hooks **para que hagan lo que nosotros queremos**. Al fin y al cabo son **funciones**.

"¿Pero será muy difícil?": A un custom hook se le puede agregar toda la lógica y complejidad que se quiera, pero no va a ser este el caso. Crearemos algo sencillo, entendible para todes.

##### Primeros pasos con nuestro hook

Nos dirigimos a nuestra carpeta `src` y creamos otra que la llamaré `hooks` y dentro tendrá un archivo de nombre `useTheme.js`.

**A saber**: la recomendación que nos da React es que nuestros hooks personalizados empiecen con `use`. 

Dentro de nuestro hook, debemos importar `React` y el `useState`. Crearemos la función `useTheme` y la exportaremos para hacerla disponible en otros componentes.

Lo siguiente que haremos es crear un `state` con `value` y `setValue` que arrancará en `null`, junto a un método que voy a llamar `handleTheme`, el cual voy a retornar y más adelante nos permitirá ejecutar el evento de nuestro botón. En un principio debería quedar así:

![React, JavaScript](https://dev-to-uploads.s3.amazonaws.com/i/99koj9qbl8d2e23spp53.png)

**Nota**: pueden obviar el `import React...` y dejarlo de esta forma `import {useState} from 'react'`. Eso eliminará una advertencia en la consola pero ambas formas son válidas.

#####Jugando con el DOM

si recuerdas, yendo a la consola y tipeando `document` podemos acceder a todo nuestro `HTML`. Entre todo ese árbol está el `body` y dentro de éste elemento podemos ver si contiene o no clases. Incluso puedes tipear en la consola `document.body` y luego intentar `document.body.classList` para hacer todo más sencillo. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/f0b61ilf9uvrcfnz9khq.png)

**Complemento**: la diferencia entre `ClassName` y `ClassList` es que el primero nos devuelve todas las clases que contenga un elemento en forma de `string` y el segundo en un `array`, lo cual ésta última opción nos permite agregar y quitar clases. Para saber más sobre esta diferencia aconsejo [leer el primer comentario de este post](https://teamtreehouse.com/community/difference-between-classlist-and-classname).

Como nos interesa acceder a este último elemento, simplemente lo vamos a guardar en una constante así como esta: `const body = document.body.classList` y debajo vamos a crear otra: `const darkTheme = 'dark'`. Y estas son las dos únicas variables que vamos a requerir.

#####Implementando la lógica

Ahora, quizá esta puede ser la parte más confusa para muches. Pero primero lo primero: cuando algo confunde, lo mejor es escribir pseudo-código y plantear el problema en nuestro lenguaje, no en el de las computadoras.

![JavaScript](https://dev-to-uploads.s3.amazonaws.com/i/2pvgqiumn9l9prv5p1x9.png)

**CONSEJO**: Lo que también nos permite la consola es ver **todos** los métodos con los que tenemos permitido interactuar por medio de su prototype:

![JavaScript](https://dev-to-uploads.s3.amazonaws.com/i/c743ali4vthrq078hem2.png)

![JavaScript](https://dev-to-uploads.s3.amazonaws.com/i/5twpnm2dwrwbzvapf5kh.png)

De todos esos métodos, vamos a utilizar tres: `contains()`, `add()` y `remove()`. Repasando rápidamente en nuestro lenguaje: si `body` contiene la clase `dark` `if(body.contains()){ ... }` quiero que lo remuevas `body.remove()`, de otra forma, agregala `body.add()`. De momento nos quedaría algo así:

![JavaScript](https://dev-to-uploads.s3.amazonaws.com/i/9hgn6c780ufrwgjv5iun.png)

Hasta ahí perfecto; pero queremos más. Queremos combinarlo con nuestro `state` y esa clase que se agrega y remueve por medio de un click quede guardada ahí. Vamos a hacer un `setValue` al momento de agregar y quitar. Finalmente, hacemos un `return { value, handleTheme }` para tenerlo disponible donde lo vayamos a utilizar.

![JavaScript, React](https://dev-to-uploads.s3.amazonaws.com/i/jrq2c4g3u35l7gc9bbz0.png)

**GRAN TRABAJO!** Ya tenemos nuestro custom hook finalizado. Ahora será momento de usarlo.

###Utilizando nuestro Custom Hook

Ya hicimos la parte más complicada, ahora sólo queda disfrutar de lo logrado hasta aquí.

Como primer paso vamos a nuestro `src/pages/index.js` e importamos nuestro hook personalizado tipeando `import useTheme from '../hooks/useTheme'`. La siguiente que haremos es cortar todo el contenido dentro de `const IndexPage = () => (...)` y reemplazarlo de la siguiente forma:

![Gatsby](https://dev-to-uploads.s3.amazonaws.com/i/iczjm29qj03ewtybuko8.png)

Lo siguiente es extraer la función de `handleTheme` que implementamos y retornamos en nuestro `useTheme.js`. Para eso, arriba del `return ( ... )` vamos a escribir `const {handleTheme} = useTheme();`. Por último, a nuestro botón le vamos a dar la funcionalidad de `handleTheme` de la siguiente forma: `<button onClick={handleTheme}>Moon</button>`.

¡Listo! Ya podemos switchear el background de nuestro sitio entre light o dark mode, porque si recuerdas, a nuestro `body` ya le avisamos que iba a recibir la clase `dark` y en nuestro hook personalizado hicimos la funcionalidad de agregarla y removerla a través de un evento `onClick`.

![CSS](https://dev-to-uploads.s3.amazonaws.com/i/elp06w306ijwwybz64a3.png)

#####Pequeño truco en Sass
Lo último que quiero enseñarte es un pequeño truco de Sass. Como sabemos, nosotros en nuestro `index.scss` tenemos un `h1{ color: $green }`. En ese mismo `h1` y en realidad puede ser en cualquier selector o elemento, vamos a tipear `body.dark & { color: $pink }`. Y eso cambiará el color de nuestro `h1` o elemento con el que quisieramos hacerlo.

![CSS](https://dev-to-uploads.s3.amazonaws.com/i/dvuttbe1ludfbiykup1f.png)

Agradezco inmensamente a aquelles que se tomaron el tiempo de leer estos artículos y ojalá les haya servido. [En este link puede acceder al código final del proyecto](https://github.com/JPGallegos1/gatsby-sass). Dudas y sugerencias, todo es bienvenido en un comentario o [me pueden escribir a mi twitter](https://twitter.com/JP__Gallegos).