Как создать таймер с помощью React

Для одного из моих текущих проектов я создал таймер до релиза в канун Нового года — 31 декабря 2022 года. Поскольку проект написан на React, я также создал таймер, используя ту же настройку.

Это первый учебник, который я написал. Я сделал все возможное, чтобы объяснить каждый шаг как можно точнее 😬.

Оглавление

  1. Инициировать проект React
  2. Создайте компонент таймера
  3. Получить код
  4. Получить расширенный код

1. Инициируйте проект React

Если вы хотите добавить таймер в существующий проект, вы можете пропустить эту часть. Если у вас еще не создан проект React, используйте консоль, чтобы перейти в папку, в которой вы хотите сохранить свой проект, используя

cd folder-name

и напишите

npx create-react-app my-app

в консоли, чтобы инициализировать проект. После того как проект будет готов, напишите

cd my-app

чтобы перейти в папку с проектом,

code .

чтобы открыть его в Visual Studio Code (если вы используете эту IDE), и

npm start

запустить проект в localhost:3000.

Дальнейшие инструкции вы можете найти в разделе create react app или в официальной документации по React.

2. Создайте компонент таймера

В папке src создайте новый файл под названием Timer.js.

Затем создайте компонент функции React arrow с тем же именем, что и файл, и добавьте оператор возврата. Не забудьте экспортировать функцию.

// Timer.js

import React from 'react';

const Timer = () => {

  return (
    <div className="timer">
    </div>
  );
};

export default Timer;
Вход в полноэкранный режим Выход из полноэкранного режима

Инициализация переменных

Мы запускаем функцию, импортируя хук useState() (встроенная функция) из React и создавая необходимые нам состояния. Для таймера такой длины нам нужны дни, часы, минуты и секунды. Я установил значение по умолчанию 0, поскольку мы имеем дело с целыми числами.

// Timer.js

import React from 'react';
import { useState } from 'react';

const Timer = () => {
  const [days, setDays] = useState(0);
  const [hours, setHours] = useState(0);
  const [minutes, setMinutes] = useState(0);
  const [seconds, setSeconds] = useState(0);

  return (
    <div className="timer">
    </div>
  );
};

export default Timer;
Вход в полноэкранный режим Выйти из полноэкранного режима

Инициализация крайнего срока

Нам нужна конкретная дата, до которой должен работать таймер. В данном случае я выбрал канун Нового года и объявил его как строковое значение (которое мы позже преобразуем в целое число) в переменной под названием deadline.

// Timer.js

import React from 'react';
import { useState } from 'react';

const Timer = () => {
  const [days, setDays] = useState(0);
  const [hours, setHours] = useState(0);
  const [minutes, setMinutes] = useState(0);
  const [seconds, setSeconds] = useState(0);
  const [seconds, setSeconds] = useState(0);

  const deadline = "December, 31, 2022";

  return (
    <div className="timer">
    </div>
  );
};

export default Timer;
Вход в полноэкранный режим Выход из полноэкранного режима

Создание функции для получения времени

Теперь давайте создадим функцию, которая будет вычислять время до этой конкретной даты. В этой функции нам понадобится наша объявленная переменная deadline, и мы можем использовать ее напрямую, поскольку она объявлена в области видимости компонента Timer.

Чтобы получить разницу между сегодняшним днем и нашим крайним сроком, я создал новую переменную под названием time и установил ее значение в значение deadline минус значение текущей даты.

Для этого мы используем встроенную в JavaScript функцию Date.parse(), которая преобразует объявленную строку deadline, которую мы передали в качестве prop, в целое число, с которым мы можем работать.

Метод Date.now() возвращает число миллисекунд, представляющее текущую дату.

// Timer.js

import React from 'react';
import { useState } from 'react';

const Timer = () => {
  const [days, setDays] = useState(0);
  const [hours, setHours] = useState(0);
  const [minutes, setMinutes] = useState(0);
  const [seconds, setSeconds] = useState(0);

  const deadline = "December, 31, 2022";

  const getTime = () => {
    const time = Date.parse(deadline) - Date.now();

  return (
    <div className="timer">
    </div>
  );
};

export default Timer;
Вход в полноэкранный режим Выход из полноэкранного режима

Вычисление значений для переменных

Поскольку время — это число в миллисекундах, теперь мы можем вычислить и установить значения дней, часов, минут и секунд до крайнего срока.

Чтобы получить значения для каждой переменной, нужно преобразовать миллисекунды в секунды, разделив время на 1000 (потому что 1000 миллисекунд — это 1 секунда).

Чтобы получить минуты, нужно разделить время на 1000 (чтобы получить секунды) и разделить на 60 (потому что в 1 минуте 60 секунд).

Чтобы получить часы, нужно разделить время в миллисекундах на 1000 (чтобы получить секунды), 60 (чтобы получить минуты) и снова 60 (потому что 1 час имеет 60 минут), суммируя здесь в скобках 1000 * 60 * 60 (можно использовать сокращение 3.600.000).

Чтобы получить дни, нужно разделить время в миллисекундах на 1000 (чтобы получить секунды), 60 (чтобы получить минуты), еще раз 60 (потому что 1 час имеет 60 минут) и 24 (потому что 1 день имеет 24 часа), обобщая здесь в скобках 1000 * 60 * 60 * 24 (можно сокращенно 86.400.000).

После получения каждого значения мы используем оператор остатка (%) для сброса значений в 0, если, например, пользователь передал 86.400.000 в миллисекундах, что равно 24 часам.

По умолчанию функция переворачивает часы, если они больше 24, например, если миллисекунды равны 36 часам, строка hours = hours % 24 устанавливает часы на 12. В зависимости от вашего случая использования, вы можете не пересчитывать часы.

Встроенная функция Math.floor() возвращает наибольшее целое число, которое меньше или равно заданному значению.

// Timer.js

import React from 'react';
import { useState } from 'react';

const Timer = () => {
  const [days, setDays] = useState(0);
  const [hours, setHours] = useState(0);
  const [minutes, setMinutes] = useState(0);
  const [seconds, setSeconds] = useState(0);

  const deadline = "December, 31, 2022";

  const getTime = () => {
    const time = Date.parse(deadline) - Date.now();

    setDays(Math.floor(time / (1000 * 60 * 60 * 24)));
    setHours(Math.floor((time / (1000 * 60 * 60)) % 24));
    setMinutes(Math.floor((time / 1000 / 60) % 60));
    setSeconds(Math.floor((time / 1000) % 60));
  };

  return (
    <div className="timer">
    </div>
  );
};

export default Timer;
Вход в полноэкранный режим Выход из полноэкранного режима

Чтобы заставить таймер отрисовываться через каждую секунду, нам нужно импортировать хук useEffect() и использовать его внутри компонента для получения текущего значения. Этот хук используется, когда состояние должно быть обновлено.

Мы будем использовать метод setInterval(), который вызывает нашу функцию getTime() с дедлайном, переданным в качестве prop, с фиксированной временной задержкой между каждым вызовом в 1000 (в миллисекундах, что составляет 1 секунду).
И поскольку эта функция вызывается только тогда, когда компонент размонтирован, мы должны очистить интервал с помощью функции clearInterval(), чтобы вызвать повторный рендеринг.

// Timer.js

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

const Timer = () => {
  const [days, setDays] = useState(0);
  const [hours, setHours] = useState(0);
  const [minutes, setMinutes] = useState(0);
  const [seconds, setSeconds] = useState(0);

  const deadline = "December, 31, 2022";

  const getTime = () => {
    const time = Date.parse(deadline) - Date.now();

    setDays(Math.floor(time / (1000 * 60 * 60 * 24)));
    setHours(Math.floor((time / (1000 * 60 * 60)) % 24));
    setMinutes(Math.floor((time / 1000 / 60) % 60));
    setSeconds(Math.floor((time / 1000) % 60));
  };

  useEffect(() => {
    const interval = setInterval(() => getTime(deadline), 1000);

    return () => clearInterval(interval);
  }, []);

  return (
    <div className="timer">
    </div>
  );
};

export default Timer;
Вход в полноэкранный режим Выход из полноэкранного режима

Вот и все.

Функциональность таймера теперь полностью настроена. Теперь вы можете стилизовать каждую переменную внутри оператора возврата компонента таймера <div className="timer></div> так, как вам нужно. Вы можете посмотреть, как я оформил свой код. Не забудьте импортировать компонент таймера в компонент приложения, чтобы он мог быть отображен.

3. Получите код

Вы можете найти код и таблицу стилей, встроенные в CodePen. Обратите внимание, что в структуре есть различия, о которых я упоминал в учебнике. В CodePen нет дополнительных файлов, и весь код находится в разделах JavaScript. Также не было сделано никаких импортов, а хуки начинаются с React.useState и React.useEffect.

4. Получите расширенный код

Люк Ширу добавил в комментариях к моему таймеру гораздо более продвинутый подход к коду, которым я хочу поделиться со всеми, кто лучше знаком с JavaScript или хочет им стать. Еще раз спасибо, что поделился кодом и сделал мою статью еще лучше.

Посмотрите подход Люка Ширу

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

const SECOND = 1000;
const MINUTE = SECOND * 60;
const HOUR = MINUTE * 60;
const DAY = HOUR * 24;

export const Timer = ({ deadline = new Date().toString() }) => {
    const parsedDeadline = useMemo(() => Date.parse(deadline), [deadline]);
    const [time, setTime] = useState(parsedDeadline - Date.now());

    useEffect(() => {
        const interval = setInterval(
            () => setTime(parsedDeadline - Date.now()),
            1000,
        );

        return () => clearInterval(interval);
    }, []);

    return (
        <div className="timer">
            {Object.entries({
                Days: time / DAY,
                Hours: (time / HOUR) % 24,
                Minutes: (time / MINUTE) % 60,
                Seconds: (time / SECOND) % 60,
            }).map(([label, value]) => (
                <div key={label} className="col-4">
                    <div className="box">
                        <p>{`${Math.floor(value)}`.padStart(2, "0")}</p>
                        <span className="text">{label}</span>
                    </div>
                </div>
            ))}
        </div>
    );
};
Вход в полноэкранный режим Выход из полноэкранного режима

Спасибо за ваше прочтение и потраченное время. Я очень ценю это!

Оцените статью
devanswers.ru
Добавить комментарий