useRef для хранения ссылок

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

Создание ссылки с useRef

Для создания ссылки используется вызов функции useRef:

import { useRef, html } from "atomico";

function Example() {
    const inputRef = useRef(null);

    return html`
        <input type="text" ref=${inputRef} />
        <button oncl ick=${() => inputRef.current.focus()}>Фокус</button>
    `;
}
  • useRef(initialValue) принимает начальное значение (null, объект, число и т.д.).
  • Свойство current хранит актуальную ссылку на элемент или данные.
  • Обновление current не вызывает повторный рендер компонента, что отличает useRef от useState.

Привязка к DOM

В Atomico ссылка часто используется для прямого взаимодействия с DOM-элементами:

const boxRef = useRef(null);

html`
    <div ref=${boxRef} style="width: 100px; height: 100px; background: red;"></div>
    <button oncl ick=${() => (boxRef.current.style.background = "blue")}>
        Изменить цвет
    </button>
`;
  • С помощью boxRef.current можно чтение и изменение свойств DOM напрямую.
  • Полезно для управления фокусом, прокруткой, размерами элементов и анимациями.

Хранение произвольных данных

Помимо работы с DOM, useRef удобно использовать для сохранения любых изменяемых значений, которые не должны триггерить ререндер:

const timerRef = useRef(null);

function startTimer() {
    timerRef.current = setInterval(() => {
        console.log("Тик");
    }, 1000);
}

function stopTimer() {
    clearInterval(timerRef.current);
}
  • Здесь timerRef.current сохраняет идентификатор таймера между вызовами функций.
  • Такой подход эффективен для хранения состояния, которое не влияет на визуальное отображение.

Отличие от useState

Главное отличие useRef от useState состоит в том, что обновление ссылки не вызывает перерисовку компонента:

Характеристика useRef useState
Сохраняет значение между рендерами Да Да
Изменение вызывает рендер Нет Да
Подходит для DOM-ссылок Да Нет
Подходит для внутренних счетчиков или таймеров Да Можно, но лишние рендеры

Это делает useRef незаменимым для оптимизации производительности, когда нужно хранить данные без повторного рендера.

Синхронизация с эффектами

Часто useRef используется вместе с useEffect для взаимодействия с DOM после монтирования компонента:

import { useRef, useEffect, html } from "atomico";

function AutoFocusInput() {
    const inputRef = useRef(null);

    useEffect(() => {
        inputRef.current.focus();
    }, []);

    return html`<input ref=${inputRef} />`;
}
  • useEffect обеспечивает доступ к элементу только после того, как компонент появился в DOM.
  • Это предотвращает ошибки null при обращении к current до рендера.

Комбинация с кастомными хуками

useRef часто включают в состав кастомных хуков для более универсального управления элементами и состоянием:

function usePrevious(value) {
    const ref = useRef();
    useEffect(() => {
        ref.current = value;
    }, [value]);
    return ref.current;
}

function Counter() {
    const [count, setCount] = useState(0);
    const prevCount = usePrevious(count);

    return html`
        <div>
            Текущее: ${count}, Предыдущее: ${prevCount}
            <button oncl ick=${() => setCount(count + 1)}>Увеличить</button>
        </div>
    `;
}
  • Хук usePrevious сохраняет предыдущее значение переменной, используя ref.current.
  • Такой подход позволяет реализовывать сложные логики без лишних рендеров.

Практические рекомендации

  • Использовать useRef для DOM-ссылок и внутренних данных, не влияющих на отображение.
  • Не использовать useRef как замену useState для значений, от которых зависит интерфейс.
  • При работе с DOM всегда проверять ref.current на null, чтобы избежать ошибок.
  • Комбинировать с useEffect для безопасного доступа к элементам после рендера.

useRef в Atomico обеспечивает эффективное хранение и управление ссылками и данными, позволяя создавать динамичные, отзывчивые компоненты без лишних перерисовок. Это ключевой инструмент для оптимизации и контроля над внутренним состоянием компонентов.