Принудительное обновление значений

При использовании функции render библиотека самостоятельно обновляет DOM-элементы через внутренние таймеры. Однако бывают ситуации, когда необходимо запустить обновление немедленно — без ожидания следующего цикла таймера.


Как работает автоматическое обновление

После вызова render(nodes, locale) библиотека:

  1. Сразу обновляет текст всех переданных элементов.
  2. Планирует следующее обновление через адаптивный интервал.

Первое обновление происходит синхронно в момент вызова render. Последующие — по таймеру.


Когда нужно принудительное обновление

  • После изменения атрибута datetime у элемента.
  • После добавления нового элемента в DOM.
  • После возвращения с другой вкладки/страницы.
  • После смены локали.
  • После изменения relativeDate.

Принудительное обновление через повторный вызов render

Самый простой способ — вызвать render ещё раз:

import { cancel, render } from 'timeago.js';

const nodes = document.querySelectorAll('.time');

// Остановить предыдущие таймеры
cancel(nodes);

// Запустить новый цикл обновления
render(nodes, 'ru');

Это сбрасывает все таймеры и инициирует немедленное обновление.


Обновление после смены datetime

import { cancel, render } from 'timeago.js';

const el = document.querySelector('#time');

// Сменить дату
el.setAttribute('datetime', new Date().toISOString());

// Принудительно переинициализировать
cancel(el);
render(el, 'ru');

Принудительное обновление через format

При использовании format (без render) каждый вызов всегда возвращает актуальный результат — нет кэширования или отложенного обновления:

import { format } from 'timeago.js';

function refreshTime(date, element) {
  element.textContent = format(date, 'ru');
}

Вызов refreshTime в любой момент гарантирует актуальное значение.


Принудительное обновление при фокусе на вкладке

Когда пользователь возвращается на вкладку, время могло сильно измениться:

import { cancel, render } from 'timeago.js';

document.addEventListener('visibilitychange', () => {
  if (!document.hidden) {
    const nodes = document.querySelectorAll('[data-timeago]');
    cancel(nodes);
    render(nodes, 'ru');
  }
});

Принудительное обновление в React через key

В React самый простой способ принудить повторный рендер — изменить key компонента:

import { useState } from 'react';
import { format } from 'timeago.js';

function TimeAgo({ date }) {
  return <time>{format(date, 'ru')}</time>;
}

function App() {
  const [refreshKey, setRefreshKey] = useState(0);

  return (
    <div>
      <TimeAgo key={refreshKey} date="2025-05-26T08:00:00Z" />
      <button onCl ick={() => setRefreshKey(k => k + 1)}>Обновить</button>
    </div>
  );
}

Принудительное обновление через useEffect

import { useEffect, useRef } from 'react';
import { render, cancel } from 'timeago.js';

function TimeNode({ date }) {
  const ref = useRef(null);

  useEffect(() => {
    if (!ref.current) return;
    cancel(ref.current);
    render(ref.current, 'ru');
    return () => cancel(ref.current);
  }, [date]); // пересоздаёт таймер при смене даты

  return <time ref={ref} dateTime={date}></time>;
}

Принудительное обновление в Vue через watch

<script setup>
import { ref, onMounted, onBeforeUnmount, watch } from 'vue';
import { render, cancel } from 'timeago.js';

const props = defineProps({ date: String });
const el = ref(null);

function init() {
  if (!el.value) return;
  cancel(el.value);
  render(el.value, 'ru');
}

onMounted(init);
onBeforeUnmount(() => cancel(el.value));

// Принудительно обновлять при смене даты
watch(() => props.date, init);
</script>

<template>
  <time ref="el" :datetime="date"></time>
</template>

Принудительное глобальное обновление

import { cancel, render } from 'timeago.js';

function refreshAll(locale = 'ru') {
  const nodes = document.querySelectorAll('[datetime]');
  cancel(nodes);
  render(nodes, locale);
}

// Обновлять каждые 5 минут
setInterval(refreshAll, 5 * 60 * 1000);

Принудительное обновление после WebSocket-события

import { cancel, render } from 'timeago.js';

socket.on('new_post', (post) => {
  // Добавить новый элемент
  addPostToDOM(post);

  // Обновить все временны́е метки
  const nodes = document.querySelectorAll('.post-time');
  cancel(nodes);
  render(nodes, 'ru');
});

Избегание двойных таймеров

При каждом вызове render создаются новые таймеры. Без предварительного cancel старые таймеры продолжают работать, что приводит к дублированию обновлений и утечкам памяти.

Правильная последовательность:

cancel(nodes); // сначала остановить старые
render(nodes, locale); // затем запустить новые