Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що робить useDeferredValue()». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)`useDeferredValue(value)` повертає **"відкладену версію" значення**, тож React може не одразу прокинути нове значення у важкі ділянки UI, щоб інтерфейс лишався відгукливим. **Ключове:** введення реагує миттєво, а "дорогий" рендер підтягується трохи пізніше.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що робить `useDeferredValue()` `useDeferredValue(value)` повертає «відкладену версію» значення. Якщо `value` часто змінюється (наприклад, при введенні в інпут), React може **не одразу** прокинути нове значення у важкі ділянки UI (списки, графіки), щоб інтерфейс лишався відгукливим. Ввід реагує миттєво, а «дорогий» рендер підтягується трохи пізніше. Міні-приклад: ```javascript const [query, setQuery] = useState(''); const deferredQuery = useDeferredValue(query); // "повільна" копія // Важкий список фільтрується за deferredQuery, а не за миттєвим query const filtered = useMemo(() => heavyFilter(items, deferredQuery), [items, deferredQuery]); ``` Поки користувач друкує, `query` змінюється одразу (інпут не лагає), а `deferredQuery` оновиться трохи пізніше - важкий рендер не «сіпається» на кожен символ. --- ## Чим `useDeferredValue()` схожий на debounce Обидва прийоми **згладжують** часті зміни, щоб не викликати важку роботу занадто часто. Схожість: - Знижують частоту «дорогих» переобчислень/рендерів при швидкому вводі. - Користувач бачить плавний UI без лагів. --- ## Чим `useDeferredValue()` відрізняється від debounce Головні відмінності - у рівні і семантиці: | Критерій | `useDeferredValue()` | Debounce (наприклад, `debounce(fn, 300)`) | | --- | --- | --- | | Де працює | Всередині React, розуміє пріоритети, інтегрований з Concurrent Rendering | Поза React (утиліта часу), «тупо» затримує виклики | | Що відкладає | **Прокидання значення** в споживачів; рендер можна перервати/поновити | **Виклик функції** за таймером після паузи | | Керування затримкою | Динамічне, без жорсткого таймера; React сам вирішує, коли «наздогнати» | Жорсткий інтервал (наприклад, 300 мс) | | Скасування/переривання | Так: рендер можна перервати, якщо прийшло важливіше оновлення | Так: скидання таймера при новому вводі, але без знань про пріоритети React | | SSR/гідратація/конкурентність | Природно сумісний | Ніяк не інтегрований | | Типові кейси | Розділити «швидкий» ввід і «важкий» UI | Мережа/обробники, обмеження частоти викликів, autocomplete API | Підсумок: **debounce - про час**, `useDeferredValue` **- про пріоритети рендеру**. --- ## Чим `useDeferredValue()` відрізняється від `startTransition()` Обидва механізми служать для «нетермінових» оновлень, але точка застосування різна: | Критерій | `useDeferredValue(value)` | `startTransition(() => setState(...))` | | --- | --- | --- | | Рівень | **Значення**: віддає «повільну» копію часто змінюваного value | **Операція/оновлення**: позначає **конкретні setState** як низькопріоритетні | | Хто ініціює | Споживач значення обирає «повільну» версію | Ти сам позначаєш частину оновлень як transition | | Контроль статусу | Немає вбудованого `isPending` | Через `useTransition()` отримуєш `isPending` | | Гранулярність | Пасивна: будь-яке місце, де використовуєш deferred value, буде «наздоганяти» пізніше | Активна: ти явно обгортаєш «важкі» оновлення в transition | | Типові кейси | Важкі мемо-обчислення/списки, що залежать від швидко змінюваного `value` | Навігація, фільтрація, запити, масштабні перебудови дерева | | Асинхронність (React 19+) | Не про async | `startTransition` можна `await`-нути (очікувати async роботу) | Коротко: - `useDeferredValue` - «дай мені версію цього значення, яку можна оновити пізніше». - `startTransition` - «оці *оновлення стану* зроби низькопріоритетними». --- ## Коли що обирати - **Важкий список/графік реагує на швидкий ввід** → почни з `useDeferredValue(query)`. Просто і майже без коду. - **Потрібно позначити пакет оновлень як «нетерміновий» і показати статус «триває оновлення»** → `const [isPending, startTransition] = useTransition(); startTransition(() => setState(...))`. - **Обмежити частоту мережевих викликів / обробників вводу** → **debounce** (мережевий шар/утиліти). Можна комбінувати: debounce на запит, `useDeferredValue` - для важкого UI. --- ## Часті патерни **Комбо «інпут + deferred фільтрація»:** ```javascript const [query, setQuery] = useState(''); const deferred = useDeferredValue(query); const list = useMemo(() => heavyFilter(items, deferred), [items, deferred]); ``` **Позначити перебудову як перехідну (з індикатором):** ```javascript const [isPending, startTransition] = useTransition(); const onTabChange = (tab: string) => { startTransition(() => setActiveTab(tab)); // велика перебудова дочірніх }; return <> <Tabs onChange={onTabChange} /> {isPending && <Skeleton />} <HeavyPane tab={activeTab} /> </>; ``` **Debounce тільки для запиту:** ```javascript const debouncedFetch = useMemo(() => debounce(fetchUsers, 300), []); useEffect(() => { debouncedFetch(query); }, [query, debouncedFetch]); ``` (і паралельно можна використати `useDeferredValue(query)` для «плавного» UI) --- ## Вижимка - `useDeferredValue` - відкладена версія **значення**. Про пріоритети, не про таймер. - Debounce - **таймер**: відкладає **виклики функцій** після паузи. - `startTransition` - позначення **оновлень стану** як низькопріоритетних, з `isPending` і (в React 19+) `await`.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.