Búsqueda de sitios web

Cómo crear un temporizador de cuenta regresiva con ganchos de reacción


Introducción

En este tutorial, creará un temporizador de cuenta regresiva usando ganchos de React para actualizar el estado y administrar los efectos secundarios en un componente de React.

Con los ganchos de React, puede crear un código más limpio, una lógica reutilizable entre los componentes y actualizar el estado sin clases.

Los temporizadores de cuenta regresiva son un componente común de la interfaz de usuario. Pueden comunicar a los usuarios cuánto tiempo han estado haciendo algo o cuánto tiempo hasta que ocurra algún evento. El evento para el que realizará la cuenta regresiva en este tutorial es el Hacktoberfest de DigitalOcean.

Al final de este tutorial, tendrá un temporizador de cuenta regresiva funcional y reutilizable utilizando los ganchos useState() y useEffect() de React.

requisitos previos

Antes de comenzar esta guía, necesitará lo siguiente:

  • Necesitará un entorno de desarrollo que ejecute Cómo instalar Node.js en Ubuntu 18.04.
  • En este tutorial, creará aplicaciones con Cómo configurar un proyecto React con Create React App
  • También necesitará conocimientos básicos de JavaScript, que puede encontrar en Mozilla Developer Network.

Este tutorial se verificó con Node.js v16.13.1, npm v8.2.0 y react v17.0.2.

Paso 1: crear un proyecto vacío

En este paso, creará un nuevo proyecto usando Create React App. Luego, eliminará el proyecto de muestra y los archivos relacionados que se instalan cuando inicia el proyecto.

Para empezar, haz un nuevo proyecto. En su terminal, ejecute el siguiente script para instalar un proyecto nuevo usando create-react-app:

  1. npx create-react-app react-hooks-timer

Una vez finalizado el proyecto, cambie al directorio:

  1. cd react-hooks-timer

En una nueva pestaña o ventana de terminal, inicie el proyecto utilizando el script de inicio Create React App. El navegador se actualizará automáticamente con los cambios, así que deje este script ejecutándose mientras trabaja:

  1. npm start

Obtendrá un servidor local en ejecución. Si el proyecto no se abrió en una ventana del navegador, puede abrirlo con http://localhost:3000/. Si está ejecutando esto desde un servidor remoto, la dirección será http://your_server_ip:3000.

Su navegador se cargará con una aplicación React generada por Create React App:

Creará un nuevo conjunto de componentes personalizados, por lo que deberá comenzar por borrar un código repetitivo para que pueda tener un proyecto vacío.

Para comenzar, abra src/App.js en un editor de texto. Este es el componente raíz que se inyecta en la página. Todos los componentes comenzarán desde aquí. Puede encontrar más información sobre App.js en Cómo configurar un proyecto React con Create React App.

Abra src/App.js con el siguiente comando:

  1. nano src/App.js

Verá un archivo como este:

import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

Luego reemplace todo en la instrucción return para devolver un conjunto de etiquetas <div>. Esto le dará una página válida que no devuelve nada. El código final se verá así:

import React from 'react';
import logo from './logo.svg';
import './App.css';

function App() {
  return (
    <div>
    </div>
  )
}

export default App;

A continuación, elimine el logotipo. Elimine la línea import logo from ./logo.svg;.

Guarde y salga del editor de texto.

Finalmente, elimine el logotipo ya que no lo usará en esta aplicación. Es una buena práctica eliminar los archivos no utilizados mientras trabaja para evitar confusiones.

En la ventana de terminal escribe el siguiente comando:

  1. rm src/logo.svg

Ahora que el proyecto está configurado, puede crear su primer componente.

Paso 2: calcular cuánto tiempo queda

En este paso, creará una función que calcule el tiempo restante entre la fecha actual y el primer día de Hacktoberfest.

Primero, configure una función llamada calculateTimeLeft:

// ...

const calculateTimeLeft = () => {

};

// ...

A continuación, dentro de la función, utilizará el objeto JavaScript Date para encontrar el año actual.

Cree una variable llamada year que se establezca en el método JavaScript date Date.getFullYear().

Agrega el siguiente código dentro de la función calculateTimeLeft:

// ...

const calculateTimeLeft = () => {
  let year = new Date().getFullYear();
}

// ...

Nota: Puede utilizar el objeto JavaScript Date para trabajar con fechas y horas.

El método Date.getFullYear() tomará el año actual.

Ahora puede usar esta variable para calcular la diferencia entre la fecha actual y el primer día de Hacktoberfest.

Dentro de la función calculateTimeLeft, agregue una nueva variable llamada difference. Establézcalo igual a un nuevo objeto Date con el siguiente código:

// ...

const calculateTimeLeft = () => {
  let year = new Date().getFullYear();

  const difference = +new Date(`10/01/${year}`) - +new Date();
}

// ...

El + antes del nuevo objeto Date es una forma abreviada de decirle a JavaScript que convierta el objeto como un número entero, lo que le da la marca de tiempo Unix del objeto representada como microsegundos desde la época.

Nota: Para este tutorial, asegúrese de que la fecha para la que está realizando la cuenta regresiva esté configurada en el futuro o encontrará un error.

Para mantener el código reutilizable, usa una plantilla de JavaScript literal y agrega la variable year junto con el mes y el día de Hacktoberfest. Hacktoberfest comienza el 1 de octubre de cada año. Cuando usa la variable year en lugar de un año codificado, siempre tendrá el año actual.

Ahora que calculó la cantidad total de milisegundos hasta que expire el temporizador de cuenta regresiva, debe convertir la cantidad de milisegundos a algo más amigable y legible por humanos.

Paso 3: Dar formato a días, horas, minutos y segundos

En este paso, creará un objeto vacío llamado timeLeft, utilizará una instrucción if para comprobar si queda tiempo y calculará el número total de horas, minutos y segundos usando matemáticas y el operador de módulo (%). Finalmente, devolverá el timeLeft.

Primero, cree el objeto vacío llamado timeLeft que luego se completará con días, horas, minutos y segundos en la instrucción if.

Agrega el siguiente código dentro de la función calculateTimeLeft:

// ...

const calculateTimeLeft = () => {
  let year = new Date().getFullYear();
  let difference = +new Date(`10/01/${year}`) - +new Date();

  let timeLeft = {};
}

// ...

Ahora cree una instrucción if que comparará la variable diference para ver si es mayor que 0.

Agrega este código dentro de la función calculateTimeLeft:

// ...

const calculateTimeLeft = () => {
  let year = new Date().getFullYear();
  let difference = +new Date(`10/01/${year}`) - +new Date();

  let timeLeft = {};

  if (difference > 0) {
    timeLeft = {
      days: Math.floor(difference / (1000 * 60 * 60 * 24)),
      hours: Math.floor((difference / (1000 * 60 * 60)) % 24),
      minutes: Math.floor((difference / 1000 / 60) % 60),
      seconds: Math.floor((difference / 1000) % 60)
    };
  }
}

// ...

En este código, redondea los números desde el día, las horas, los minutos y los segundos hacia abajo y elimina el resto para obtener un valor de número entero. Luego puede comparar la diferencia para ver si es mayor que 0.

Finalmente, debe devolver timeLeft para que pueda usar el valor en otra parte del componente.

Agrega este código dentro de la función calculateTimeLeft:

// ...

const calculateTimeLeft = () => {
  let year = new Date().getFullYear();
  let difference = +new Date(`10/01/${year}`) - +new Date();

  let timeLeft = {};

  if (difference > 0) {
    timeLeft = {
      days: Math.floor(difference / (1000 * 60 * 60 * 24)),
      hours: Math.floor((difference / (1000 * 60 * 60)) % 24),
      minutes: Math.floor((difference / 1000 / 60) % 60),
      seconds: Math.floor((difference / 1000) % 60)
    };
  }

  return timeLeft;
}

// ...

Ahora que ha creado una función que calcula el tiempo restante hasta Hacktoberfest, puede agregar el estado de la aplicación que controlará y actualizará su temporizador.

Paso 4: actualizar el estado de su aplicación con useState y useEffect

Con React Hooks, puede agregar capacidades de administración de estado a los componentes funcionales existentes sin convertirlos en una clase.

En este paso, importará los ganchos useState y useEffect de React para administrar el estado en este componente.

En la parte superior del archivo App.js, agrega useState y useEffect en tu declaración de importación:

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

// ...

Este código le dice a React que desea usar estos ganchos específicos y su funcionalidad que está disponible en React.

Para que el temporizador de cuenta regresiva funcione, deberá conectar el método de tiempo restante que codificamos previamente para actualizar el estado:

Agregue este código después de la función calculateTimeLeft:

// ...

const [timeLeft, setTimeLeft] = useState(calculateTimeLeft());

// ...

Esta sintaxis de JavaScript se denomina desestructuración de matrices.

El método useState acepta un parámetro para establecer el estado inicial y devuelve una matriz que contiene el estado actual y una función para establecer el estado.

timeLeft llevará nuestro objeto de intervalos de tiempo restante y nos proporcionará un método para establecer el estado. En la carga del componente, el valor de timeLeft se establece en el valor de tiempo restante actual.

A continuación, usará el gancho useEffect para lidiar con los efectos secundarios del componente.

Nota: Un efecto secundario es cualquier cosa que afecta algo fuera del alcance de la función que se está ejecutando.

En esta solución, utilizará un método setTimeout dentro del enlace useEffect. setTimeout y el método similar setInterval son patrones comunes de React cuando se usan dentro del gancho useEffect.

La mayoría de los comportamientos asíncronos como el método setTimeout en React se definen con una combinación de los ganchos useEffect y useState.

Nota: Puede leer más sobre cuándo y cómo usar métodos como setTimeout y setInterval en esta sección de React Docs.

Agrega este código después de la función useState():

// ...

const [timeLeft, setTimeLeft] = useState(calculateTimeLeft());

useEffect(() => {
  const timer = setTimeout(() => {
    setTimeLeft(calculateTimeLeft());
  }, 1000);
});

// ...

El useEffect es lo que actualiza la cantidad de tiempo restante. De forma predeterminada, React volverá a invocar el efecto después de cada procesamiento.

Cada vez que la variable timeLeft se actualiza en el estado, se activa useEffect. Cada vez que se dispara, configuramos un temporizador de 1 segundo (o 1,000 ms), que actualizará el tiempo restante después de que haya transcurrido ese tiempo.

El ciclo continuará cada segundo después de eso.

Para ayudar a eliminar la posibilidad de acumular tiempos de espera y causar un error, agregue el método clearTimeout dentro del gancho useEffect también.

Agregue un método clearTimeout y pase la variable timer como parámetro:

// ...

useEffect(() => {
  const timer = setTimeout(() => {
    setTimeLeft(calculateTimeLeft());
  }, 1000);

  return () => clearTimeout(timer);
});

// ...

La función return se ejecuta cada vez que useEffect ejecuta el timer excepto en la primera ejecución del componente y borrará el tiempo de espera si el componente está desmontado.

Ahora que su estado está configurado en el objeto calculateTimeLeft() y se está actualizando dentro de su gancho de efecto, puede usarse para construir su componente de visualización.

Paso 5: usar Object.keys

En este paso, usará Object.keys para iterar sobre el objeto timeLeft y crear un componente de visualización. Utilizará el componente de visualización para mostrar el tiempo que queda antes de que comience el Hacktoberfest.

Primero, cree una nueva variable bajo el gancho useEffect llamada timerComponents:

// ...

const timerComponents = [];

// ...

Después de iterar sobre las claves en timeLeft, utilizará esta variable para impulsar un nuevo componente JSX con el tiempo restante.

Luego, use Object.keys para iterar sobre el objeto timeLeft que devolvió de su función calculateTimeLeft.

Agregue este código en la variable timerComponents:

// ...

const timerComponents = [];

Object.keys(timeLeft).forEach((interval) => {
  if (!timeLeft[interval]) {
    return;
  }

  timerComponents.push(
    <span>
      {timeLeft[interval]} {interval}{" "}
    </span>
  );
});

// ...

Aquí el código recorre las propiedades del objeto timeLeft. Si el intervalo del temporizador tiene un valor mayor que cero, agrega un elemento a la matriz timerComponents.

Nota: El { } adicional en el código se usa para que los intervalos que muestran el tiempo restante no se crucen entre sí cuando se muestran en la pantalla.

El {} le permite usar JavaScript dentro de su JSX y el agrega el espacio.

Ahora está listo para agregar el nuevo JSX en la instrucción return de los componentes de la aplicación para mostrar el tiempo restante hasta el Hacktoberfest.

Paso 6: mostrar el tiempo restante

En este paso, agregará componentes JSX a la instrucción return del componente de la aplicación. Usarás un operador ternario para verificar si queda tiempo o si es hora de Hacktoberfest,

Para usar la matriz timerComponents, debe verificar su longitud y devolverla o informar al usuario que el temporizador ya ha transcurrido.

Agregue este código dentro de la instrucción return:

// ...

return (
  <div>
    {timerComponents.length ? timerComponents : <span>Time's up!</span>}
  </div>
);

// ...

En los componentes de React JSX, utiliza un operador ternario en lugar de una declaración if de JavaScript. Esto se debe a que solo se permiten expresiones dentro de JSX.

La línea de código timerComponents.length comprueba si hay algo dentro de la matriz timerComponents y lo muestra si lo hay; de lo contrario, muestra Times up!.

A continuación, agregará dos componentes JSX más a la instrucción return para que el usuario sepa qué cuenta regresiva:

// ...

return (
  <div>
    <h1>Hacktoberfest 2020 Countdown</h1>
    <h2>With React Hooks!</h2>
    {timerComponents.length ? timerComponents : <span>Time's up!</span>}
  </div>
);

// ...

Para usar el año actual en lugar de codificar 2020, puede crear una nueva variable de estado y establecer el estado inicial en new Date().getFullYear();.

Después de la primera variable useState(), agregue este código:

// ...

const [timeLeft, setTimeLeft] = useState(calculateTimeLeft());
const [year] = useState(new Date().getFullYear());

// ...

Este método tomará el año actual como lo usó en la función calculateTimeLeft.

Luego puede eliminar el 2020 codificado de forma rígida de su h1 y reemplazarlo con year:

// ...

return (
  <div>
    <h1>Hacktoberfest {year} Countdown</h1>
    <h2>With React Hooks!</h2>
    {timerComponents.length ? timerComponents : <span>Time's up!</span>}
  </div>
);

// ...

Esto mostrará su variable de estado, que ahora siempre tendrá el año actual. Su proyecto completo se verá así:

Consulte este repositorio de GitHub para ver el código completo.

Conclusión

En este tutorial, creó un componente de interfaz de usuario de cuenta regresiva utilizando los ganchos useState y useEffect para administrar y actualizar el estado de su aplicación.

Desde aquí, puede continuar su aprendizaje con el estilo de los componentes de React para crear una interfaz de usuario de cuenta regresiva más atractiva.

También puede seguir la serie completa Cómo codificar en React.js en DigitalOcean para aprender aún más sobre el desarrollo con React.

Artículos relacionados: