Глубокое Погружение в Работу с Таймерами в React

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Работа с таймерами в React требует понимания нескольких ключевых концептов. Давайте разберем, как создать надежные таймеры с нуля, и познакомимся с готовыми решениями.

Базовые Принципы Работы с Таймерами

При реализации таймеров в React важно учитывать:

  1. Очистку ресурсов при размонтировании компонента

  2. Корректную работу с замыканиями

  3. Обработку изменений состояния компонента

Почему useEffect и useRef Так Важны для Таймеров?

При работе с таймерами в React, комбинация useEffect и useRef решает несколько критических проблем, которые могут возникнуть при наивной реализации. Давайте разберем, почему эти хуки являются ключевыми компонентами надежного таймера.

Роль useEffect

useEffect выступает как "менеджер жизненного цикла" таймера. Когда компонент монтируется или изменяется состояние active, useEffect создает новый интервал. Функция очистки (cleanup) гарантирует, что старый интервал будет удален перед созданием нового или при размонтировании компонента. Без cleanup-функции в useEffect, каждое изменение зависимостей создавало бы новый интервал, не очищая старый, что приводило бы к множественным одновременно работающим таймерам.

Магия useRef

useRef решает несколько критических проблем:

В отличие от обычных переменных, которые пересоздаются при каждом рендере, useRef сохраняет значение между рендерами. Это особенно важно для:

  1. Хранения ID интервала для последующей очистки

  2. Сохранения актуальной версии callback-функции

Без useRef, функция в setInterval замыкается на той версии callback, которая была актуальна при создании эффекта. С useRef мы всегда имеем доступ к актуальной версии callback.

Реализация Интервала

Начнем с простого интервала. Вот полная реализация хука useInterval:

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

export const useInterval = (callback: () => void, interval = 1000) => {
  const [active, setActive] = useState(true);
  const intervalIdRef = useRef<ReturnType<typeof setInterval>>();
  const callbackRef = useRef(callback);
  
  // Обновляем референс при изменении callback
  callbackRef.current = callback;

  useEffect(() => {
    if (!active) return;

    // Используем callbackRef для доступа к актуальной версии callback
    intervalIdRef.current = setInterval(() => callbackRef.current(), interval);
    
    // Очистка при размонтировании или изменении зависимостей
    return () => {
      clearInterval(intervalIdRef.current);
    };
  }, [active, interval]);

  return {
    active,
    pause: () => setActive(false),
    resume: () => setActive(true),
    toggle: () => setActive(prev => !prev)
  };
};

Разбор Механизма:

  1. useRef для callback:

    const callbackRef = useRef(callback);
    callbackRef.current = callback;

    Используем useRef для хранения актуальной версии callback-функции, избегая проблем с замыканиями.

  2. Управление состоянием:

    const [active, setActive] = useState(true);
    

    Состояние active контролирует работу интервала.

  3. Эффект и очистка

    useEffect(() => {
      if (!active) return;
      intervalIdRef.current = setInterval(() => callbackRef.current(), interval);
      return () => clearInterval(intervalIdRef.current);
    }, [active, interval]);

Готовое Решение: @sibericancode/reactuse

Хотя понимание механизма работы таймеров важно, в реальных проектах часто удобнее использовать готовые, протестированные решения. Библиотека @sibericancode/reactuse предоставляет все эти функции и даже больше:

  1. Полная типизация TypeScript

  2. Дополнительные опции и callback'и

  3. Оптимизированная производительность

  4. Тестовое покрытие

  5. Регулярные обновления и поддержка

import { useTimer } from '@sibericancode/reactuse';

const { active, days, hours, minutes, seconds } = useTimer(86400, {
  immediately: true,
  onExpire: () => console.log('Готово!'),
  onTick: (s) => console.log(`Осталось ${s} секунд`)
});

Вместо того чтобы реализовывать эти механизмы самостоятельно, вы можете сосредоточиться на бизнес-логике вашего приложения, используя надежные и проверенные инструменты из https://siberiacancode.github.io/reactuse/

Источник: https://habr.com/ru/articles/889690/


Интересные статьи

Интересные статьи

Патологический страх, который многие питают к смартфонам Huawei, чаще всего не имеет ничего общего с реальностью, а спровоцирован надуманными страшилками из интернета. Потому что на самом деле аппарат...
Интеграция – это техническое решение, которое позволяет передавать данные лидов в трекинговую систему CPA-сети с целью отслеживания открутки в режиме реального времени, анализа трафика в разбивке по и...
Меня зовут Александр, я руковожу направлением больших данных в Битрикс24. Клиенты нашего сервиса хранят миллиарды файлов: от документов до фотографий, — а моя команда предоставляет возможность строить...
Битрикс24 — корпоративное SaaS-решение (Software as a Service, программное обеспечение как услуга), которым пользуются компании разного масштаба и профиля для коммуникации между сотрудниками, хран...
Я давно знаком с Битрикс24, ещё дольше с 1С-Битрикс и, конечно же, неоднократно имел дела с интернет-магазинами которые работают на нём. Да, конечно это дорого, долго, местами неуклюже...