Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Що таке customRef і як зробити ref із затримкою оновлення?

customRef дає змогу створити ref з власною логікою відстеження й сповіщення про зміни. Фабрика отримує дві функції:

  • track() - зареєструвати залежність (викликати при читанні);
  • trigger() - сповістити залежних про зміну (викликати, коли значення справді змінилося).

Класичний приклад - ref із затримкою (debounce):

import { customRef } from 'vue';

export function useDebouncedRef(initial, delay = 300) {
  let value = initial;
  let timeout;

  return customRef((track, trigger) => ({
    get() {
      track();
      return value;
    },
    set(newValue) {
      clearTimeout(timeout);
      timeout = setTimeout(() => {
        value = newValue;
        trigger();
      }, delay);
    },
  }));
}
<script setup>
const query = useDebouncedRef('', 400);

watch(query, (value) => search(value));   // запит лише після паузи у введенні
</script>

<template>
  <input v-model="query">
</template>

Поле оновлюється в шаблоні... тільки після затримки - бо значення змінюється в set із запізненням. Для пошуку це прийнятно, а для звичайного введення - ні: користувач не бачитиме набраного тексту. Тому частіше роблять інакше: звичайний ref для поля і окремий debounced-ref (чи watch з затримкою) для запиту.

Інші застосування customRef:

  • ref, синхронізований з localStorage - читання з кешу, запис у сховище;
  • ref над зовнішнім джерелом (значення з бібліотеки, що має власні події змін) - trigger() з обробника події бібліотеки;
  • валідація чи нормалізація при записі (обрізати пробіли, обмежити діапазон);
  • лінива ініціалізація дорогого значення при першому читанні.

Що варто знати:

  • get має повертати однакове значення для однакового стану - Vue може викликати його багато разів;
  • не забувати track() - без нього шаблон не оновиться, хоча trigger() викликано;
  • документація окремо застерігає від get, що щоразу створює новий об'єкт: якщо такий ref передано в props, кожен рендер батька дає дочірньому компоненту «нове» значення, і той перерендерюється без потреби;
  • готові варіанти вже є у VueUse: refDebounced, useLocalStorage, refThrottled.

Докладніше в документації: customRef

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання