Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Як типізувати useRef()?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)`useRef` створює **об'єкт-посилання** (`{ current: ... }`), який React зберігає між рендерами, і типізується як `function useRef<T>(initialValue: T): MutableRefObject<T>`. **Ключове:** якщо ref спочатку `null` (наприклад, посилання на DOM), тип потрібно вказувати явно, наприклад `useRef<HTMLInputElement | null>(null)`.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## 1. Що робить `useRef` `useRef` створює **об'єкт-посилання** (`{ current: ... }`), який React зберігає між рендерами. Тип сигнатури: ```javascript function useRef<T>(initialValue: T): MutableRefObject<T>; ``` --- ## 2. Базова типізація ```javascript const countRef = useRef<number>(0); countRef.current++; // current - число ``` TypeScript знає, що `countRef.current` - `number`. Якщо передаєш початкове значення, TS виведе тип автоматично: ```javascript const flagRef = useRef(false); // inferred: MutableRefObject<boolean> ``` --- ## 3. Якщо спочатку `null` (DOM або lazy-посилання) Коли `ref` спочатку `null` - обов'язково вказуємо тип явно: ```javascript // Посилання на DOM-елемент const inputRef = useRef<HTMLInputElement | null>(null); ``` Тут `current` може бути `null` до монтування. При використанні: ```javascript inputRef.current?.focus(); ``` Безпечно: `?.` захищає від `null`. --- ## 4. Передавання `ref` в елемент ```javascript export function Form() { const inputRef = useRef<HTMLInputElement | null>(null); return <input ref={inputRef} type="text" />; } ``` TypeScript сам знає, що `inputRef.current` - `HTMLInputElement | null`. > Для різних елементів: > > - `HTMLDivElement` > - `HTMLButtonElement` > - `HTMLFormElement` > - `HTMLTextAreaElement` > - `HTMLAnchorElement` > і т.д. --- ## 5. Якщо потрібно тільки зберігати значення (а не DOM) ```javascript const intervalId = useRef<number | null>(null); useEffect(() => { intervalId.current = window.setInterval(() => console.log('tick'), 1000); return () => clearInterval(intervalId.current!); }, []); ``` Корисно для зберігання mutable-змінних без ререндера. --- ## 6. Приклад з `forwardRef` ```javascript type InputProps = React.ComponentProps<"input">; const Input = React.forwardRef<HTMLInputElement, InputProps>((props, ref) => { return <input ref={ref} {...props} />; }); // Використання const inputRef = useRef<HTMLInputElement>(null); <Input ref={inputRef} />; ``` `forwardRef` приймає два параметри типів: ```javascript React.forwardRef<Тип_елемента, Тип_пропсів>() ``` --- ## 7. Коли потрібен `useRef<T | null>(null)` vs `useRef<T>(...)` | Сценарій | Тип | | --- | --- | | DOM-елемент (монтується пізніше) | `useRef<T \| null>(null)` | | Проста змінна (число, об'єкт тощо) | `useRef<T>(значення)` | | Lazy-ініціалізація | `useRef<T \| null>(null)` | --- ## 8. "Readonly ref" (незмінне посилання) Якщо посилання **не змінюватиметься вручну**, можна використати `React.RefObject<T>`: ```javascript const divRef: React.RefObject<HTMLDivElement> = useRef(null); ``` `RefObject` = `{ readonly current: T | null }` Використовується, коли ти просто передаєш `ref` без модифікацій. --- ## 9. Приклад: клік поза елементом ```javascript function Dropdown() { const menuRef = useRef<HTMLDivElement | null>(null); useEffect(() => { function handleClick(e: MouseEvent) { if (!menuRef.current?.contains(e.target as Node)) { console.log("Clicked outside"); } } document.addEventListener("click", handleClick); return () => document.removeEventListener("click", handleClick); }, []); return <div ref={menuRef}>Menu</div>; } ``` `menuRef.current` типізований коректно. `contains()` викликається безпечно. --- ## Підсумок | Сценарій | Типізація | | --- | --- | | Проста ref-змінна | `useRef<number>(0)` | | DOM ref | `useRef<HTMLDivElement \| null>(null)` | | ref на `<input>` | `useRef<HTMLInputElement \| null>(null)` | | ref для таймера / id | `useRef<number \| null>(null)` | | Тільки читання | `React.RefObject<T>` | | З `forwardRef` | `React.forwardRef<T, Props>()` | --- > Коротко: > > - Завжди додавай `| null`, якщо `ref` на DOM. > - Не пиши `any`. Використовуй точний тип елемента (`HTMLDivElement`, `HTMLInputElement` тощо). > - Для зберігання "mutable" даних без ререндера - `useRef<T>()`. > - Для посилань між компонентами - `forwardRef()` з generic.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.