Для одного из моих текущих проектов я создал таймер до релиза в канун Нового года — 31 декабря 2022 года. Поскольку проект написан на React, я также создал таймер, используя ту же настройку.
Это первый учебник, который я написал. Я сделал все возможное, чтобы объяснить каждый шаг как можно точнее 😬.
Оглавление
- Инициировать проект React
- Создайте компонент таймера
- Получить код
- Получить расширенный код
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>
);
};
Спасибо за ваше прочтение и потраченное время. Я очень ценю это!