Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Як типізувати стан за допомогою useState()?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**useState()** зазвичай виводить тип автоматично з початкового значення (`useState(0)` дає `number`). **Ключове:** тип потрібно вказувати явно через дженерик `<T>`, коли початкове значення `null`/`undefined`, або коли потрібні union, об'єкти чи масиви.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Базові випадки ```javascript // Type inferred from the literal const [count, setCount] = useState(0); // number const [title, setTitle] = useState("Hello"); // string const [open, setOpen] = useState(false); // boolean ``` Коли **потрібно вказати тип явно**: - початкове значення null / undefined; - складні об'єднання (union), об'єкти, масиви; - хочеш звузити тип (наприклад, літеральні типи). ```javascript // Explicit typing with null const [user, setUser] = useState<User | null>(null); // Union type Status = "idle" | "loading" | "success" | "error"; const [status, setStatus] = useState<Status>("idle"); // Literal variants const [variant, setVariant] = useState<"primary" | "ghost">("primary"); ``` --- ## Об'єкти та часткові оновлення ```javascript type Form = { name: string; age: number }; const [form, setForm] = useState<Form>({ name: "", age: 0 }); // Update based on the previous state setForm(prev => ({ ...prev, name: "Tim" })); ``` > Поради > • Тип у prev виводиться автоматично. > • Для багатокрокових форм і складної логіки розглянь useReducer. --- ## Масиви та колекції ```javascript const [items, setItems] = useState<string[]>([]); // Adding an item setItems(prev => [...prev, "new"]); // Set/Map (mutable!) - create new instances const [ids, setIds] = useState<Set<string>>(new Set()); setIds(prev => new Set(prev).add("42")); ``` --- ## Nullable / Optional правильно ```javascript // Better: an explicit union with null const [el, setEl] = useState<HTMLDivElement | null>(null); // Same with undefined const [token, setToken] = useState<string | undefined>(undefined); ``` > Не використовуй «абияк» через as any - це ламає гарантії TS. --- ## Лінивий ініціалізатор (для дорогих обчислень) ```javascript const [big, setBig] = useState<number>(() => heavyCompute()); // The function runs once, on mount. ``` --- ## Похідні типи та «вузькі» літерали ```javascript // From API types type User = ApiUser & { fullName: string }; // A narrow literal via a const assertion const [align, setAlign] = useState<"left" | "center" | "right">("left"); // Or derive it from a settings object: const ALIGN = ["left", "center", "right"] as const; type Align = (typeof ALIGN)[number]; const [a, setA] = useState<Align>("left"); ``` --- ## Стан запиту (дискриміновані union) ```javascript type LoadState = | { status: "idle" } | { status: "loading" } | { status: "success"; data: Post[] } | { status: "error"; error: string }; const [state, setState] = useState<LoadState>({ status: "idle" }); setState({ status: "loading" }); // ... setState({ status: "success", data }); ``` > Зручно для вичерпних switch без «default». --- ## Типи сетера та функцій оновлення ```javascript const [n, setN] = useState(0); // Type: React.Dispatch<React.SetStateAction<number>> // You can pass a function that receives prev setN(prev => prev + 1); ``` --- ## Контрольовані інпути ```javascript const [value, setValue] = useState(""); const onChange = (e: React.ChangeEvent<HTMLInputElement>) => setValue(e.target.value); ``` --- ## Коли явно вказувати дженерик Вказуй `<T>`, якщо: - початкове значення null/undefined; - масиви/об'єкти/union; - хочеш «зафіксувати» точний тип (наприклад, string vs string | undefined). Приклади коротко: ```javascript // good const [data, setData] = useState<Post[] | null>(null); // good const [map, setMap] = useState<Map<string, number>>(new Map()); // good const [mode, setMode] = useState<"view" | "edit">("view"); // bad - too broad, any const [unknown, setUnknown] = useState<any>(null); ``` --- ## Часті помилки і як їх уникнути - Ініціалізація useState(null) без типу -> стане null, і далі TS скаржиться. Виправлення: useState<User | null>(null) - Мутування складних структур (Set/Map, об'єкти) -> React не побачить зміну. Виправлення: створюй нову структуру. - Стан, зав'язаний на безліч гілок -> заплутаний union. Виправлення: подумай про useReducer. --- ### Підсумок 1. Довіряй виведенню типів, **але** задавай `<T>` при null/undefined і складних формах. 2. Для об'єктів і масивів - **іммутабельні** оновлення. 3. Для сценаріїв завантаження - **дискриміновані union**. 4. Не бійся лінивого ініціалізатора та літеральних типів - це робить стан точним і надійним.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.