Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що робить useDeferredValue() при роботі з асинхронністю?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**`useDeferredValue(value)`** відкладає оновлення значення, щоб React міг спочатку відрендерити швидкі й важливі частини інтерфейсу, а "важкі" чи асинхронні частини оновити трохи пізніше. **Ключове:** це частина React Concurrent Rendering, яка позначає залежні від значення оновлення як низькопріоритетні, тому поле вводу залишається відзивчивим, поки важкий рендер чи запит виконується з невеликою затримкою.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що робить `useDeferredValue()` > `useDeferredValue(value)` - відкладає оновлення значення, > щоб React міг **спочатку відрендерити швидкі й важливі частини інтерфейсу**, > а "важкі" чи асинхронні частини оновити трохи пізніше. Іншими словами: > React робить **UI відзивчивим**, не блокуючи рендеринг повільних компонентів. --- ## Просте пояснення Уяви поле пошуку, де при кожному введенні символу йде запит на сервер: ```javascript <input value={query} onChange={e => setQuery(e.target.value)} /> <SearchResults query={query} /> ``` Проблема: - користувач швидко друкує - `query` змінюється на кожен символ; - кожен рендер запускає фільтрацію або мережевий запит; - UI починає "лагати" (гальмувати при введенні). --- ## 1. Як вирішує `useDeferredValue` ```javascript import { useState, useDeferredValue, Suspense } from 'react'; import useSWR from 'swr'; const fetcher = (url) => fetch(url).then(r => r.json()); function SearchResults({ query }) { const { data } = useSWR(`/api/search?q=${query}`, fetcher, { suspense: true }); return <ul>{data.results.map(r => <li key={r}>{r}</li>)}</ul>; } export default function Search() { const [query, setQuery] = useState(''); const deferredQuery = useDeferredValue(query); return ( <> <input value={query} onChange={(e) => setQuery(e.target.value)} placeholder="Пошук..." /> <Suspense fallback={<p>Завантаження...</p>}> <SearchResults query={deferredQuery} /> </Suspense> </> ); } ``` Що відбувається: 1. Користувач швидко вводить текст (`query` оновлюється миттєво). 2. React **не поспішає оновлювати важкий компонент** (`SearchResults`) для кожного символу. 3. Він **призупиняє** оновлення `deferredQuery`, поки не стане "вільним". 4. Щойно користувач перестав активно вводити -> React оновлює `deferredQuery`. У результаті: - поле вводу залишається відзивчивим; - дорогі обчислення і запити не блокують UI. --- ## 2. Поведінка на практиці | Подія | `query` | `deferredQuery` | Що робить React | |---|---|---|---| | Користувач набирає "React" | швидко змінюється: R -> Re -> Rea -> ... | залишається позаду | React рендерить тільки input | | Користувач зупинився | | наздоганяє `query` | завантажує дані для "React" | --- ## 3. Відмінність від `startTransition()` | Хук | Що робить | |---|---| | `useDeferredValue(value)` | відкладає *використання значення* (реактивна версія) | | `startTransition(callback)` | відкладає *виконання оновлення стану* | Приклад еквівалентної поведінки: ```javascript // варіант зі startTransition import { startTransition } from 'react'; function onChange(e) { const value = e.target.value; setImmediateQuery(value); // оновлюємо швидко (input) startTransition(() => setDeferredQuery(value)); // відкладено - пошук } ``` `useDeferredValue()` робить те саме, але декларативно: ```javascript const deferredQuery = useDeferredValue(query); ``` --- ## 4. Типові кейси використання | Кейс | Що робить `useDeferredValue` | |---|---| | **Пошук** | відкладає оновлення списку результатів, щоб ввід не лагав | | **Великі списки** | оновлює рендер списку трохи пізніше, щоб UI залишався відзивчивим | | **Suspense-завантаження даних** | дозволяє показувати старі дані, поки нові підвантажуються | | **Фільтри / сортування** | не перерендерює таблицю при кожному кліку | | **Графіки і візуалізація** | рендерить оновлення тільки коли React "вільний" | --- ## 5. Приклад з візуальним ефектом (висока навантаженість) ```javascript function HeavyList({ filter }) { const items = Array.from({ length: 5000 }, (_, i) => `Елемент ${i}`); const filtered = items.filter(i => i.toLowerCase().includes(filter.toLowerCase())); return ( <ul>{filtered.map(i => <li key={i}>{i}</li>)}</ul> ); } export function Search() { const [filter, setFilter] = useState(''); const deferredFilter = useDeferredValue(filter); return ( <> <input value={filter} onChange={e => setFilter(e.target.value)} placeholder="Фільтр..." /> <HeavyList filter={deferredFilter} /> </> ); } ``` При швидкому введенні: - поле вводу реагує миттєво (рендер "не блокується"); - список оновлюється з невеликою затримкою (трохи пізніше). --- ## 6. Як це працює "під капотом" `useDeferredValue`: - повертає **"затриману копію" значення**; - позначає оновлення, що залежать від нього, як **незначні** (low priority); - React виконує ці оновлення **тільки коли UI вільний**; - якщо під час очікування приходить нове значення - старе ігнорується. Це частина **React Concurrent Rendering** - нового механізму, де React сам вирішує, **що оновити спочатку, а що почекає**. --- ## ПІДСУМОК | Що робить | Навіщо потрібно | |---|---| | Відкладене оновлення значення | запобігає лагам при частих оновленнях | | Не блокує ввід і швидкі оновлення | UI залишається відзивчивим | | Дозволяє плавно працювати з Suspense | старі дані залишаються на екрані | | Використовує низький пріоритет рендера | React робить "розумний" план оновлень | | Чудово підходить для пошуку, фільтрів, списків | зменшує зайві запити і рендери | --- ### Коротко: > `useDeferredValue()` - це спосіб сказати React: > "Ось нове значення, але не поспішай з його рендером - онови, коли буде час." > > Він робить інтерфейс **плавним і відзивчивим**, > особливо при **асинхронному завантаженні даних або рендері важких компонентів**.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.