Ҳуккҳо дар React чӣ гунаанд?
sobes.tech AI
Ҷавоб аз AI
У React, начиная с версії 16.8, хуки надають функціональним компонентам можливість керувати станом та використовувати життєві цикли, які раніше були доступні лише в класових компонентах.
Ось основні вбудовані хуки:
-
useState: Дозволяє додати внутрішній стан до функціональної компоненти. Повертає пару: поточний стан і функцію для його оновлення.// Приклад useState import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); // Ініціалізація стану з 0 return ( <div> <p>Ви натиснули {count} разів</p> <button onClick={() => setCount(count + 1)}> Натисни мене </button> </div> ); } -
useEffect: Дозволяє виконувати побічні ефекти у функціональних компонентах. Подібно до методів життєвого циклу класових компонентів (componentDidMount,componentDidUpdate,componentWillUnmount).// Приклад useEffect import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // Виконується після кожного рендеру useEffect(() => { document.title = `Ви натиснули ${count} разів`; }); // Виконується лише при першому рендері (порожній масив залежностей) useEffect(() => { console.log('Компонент змонтовано'); return () => { console.log('Компонент демонтується'); // Функція очищення }; }, []); // Виконується при зміні count useEffect(() => { console.log('Count змінився:', count); }, [count]); return ( <div> <p>Ви натиснули {count} разів</p> <button onClick={() => setCount(count + 1)}> Натисни мене </button> </div> ); } -
useContext: Дозволяє підписатися на зміни контексту React. Приймає об'єкт контексту, створений за допомогоюReact.createContext().// Приклад useContext import React, { useContext } from 'react'; const ThemeContext = React.createContext('light'); // Створення контексту function ThemedButton() { const theme = useContext(ThemeContext); // Використання контексту return ( <button className={theme}> Кнопка в темі {theme} </button> ); } function App() { return ( <ThemedButton /> ); } -
useReducer: АльтернативаuseStateдля управління більш складним станом, який включає кілька підстанів або коли наступний стан залежить від попереднього. Подібно редюсерам у Redux.// Приклад useReducer import React, { useReducer } from 'react'; const initialState = { count: 0 }; function reducer(state, action) { switch (action.type) { case 'increment': return { count: state.count + 1 }; case 'decrement': return { count: state.count - 1 }; default: throw new Error(); } } function Counter() { const [state, dispatch] = useReducer(reducer, initialState); return ( <> Кількість: {state.count} <button onClick={() => dispatch({ type: 'increment' })}>+</button> <button onClick={() => dispatch({ type: 'decrement' })}>-</button> </> ); } -
useCallback: Мемоізує функцію зворотнього виклику. Повертає меморизовану версію колбека, яка змінюється лише при зміні однієї з залежностей. Корисно для запобігання непотрібних повторних рендерів дочірніх компонентів при передачі колбеків.// Приклад useCallback import React, { useState, useCallback } from 'react'; function Parent({ addTodo }) { const [count, setCount] = useState(0); const handleAddTodo = useCallback(() => { addTodo(); }, [addTodo]); // Залежність від addTodo return ( <> <button onClick={() => setCount(count + 1)}> Збільшити лічильник </button> <Child onAddItem={handleAddTodo} /> </> ); } function Child({ onAddItem }) { console.log('Child рендериться'); // Буде рендеритись лише при зміні onAddItem return <button onClick={onAddItem}>Додати елемент</button>; } -
useMemo: Мемоізує обчислюване значення. Повертає меморизоване значення, яке пересчитывається лише при зміні однієї з залежностей. Корисно для продуктивності при дорогих обчисленнях.// Приклад useMemo import React, { useMemo, useState } from 'react'; function expensiveCalculation(num) { console.log('Виконується дороге обчислення...'); for (let i = 0; i < 1000000; i++) { num += 1; } return num; } function Example() { const [count, setCount] = useState(0); const [todos, setTodos] = useState([]); const calculation = useMemo(() => expensiveCalculation(count), [count]); // Залежність від count const addTodo = () => { setTodos(t => [...t, "Новий завдання"]); }; return ( <div> <div> <h2>Мої завдання</h2> {todos.map((todo, index) => ( <p key={index}>{todo}</p> ))} <button onClick={addTodo}>Додати завдання</button> </div> <hr /> <div> Лічильник: {count} <button onClick={() => setCount(c => c + 1)}>+</button> <h2>Дороге обчислення</h2> {calculation} </div> </div> ); } -
useRef: Дозволяє створити мутабельний ref, який зберігається протягом усього життєвого циклу компонента. Часто використовується для доступу до елементів DOM або збереження будь-якого мутабельного значення, яке не викликає перерисовки при зміні.// Приклад useRef import React, { useRef, useEffect } from 'react'; function TextInputWithFocusButton() { const inputEl = useRef(null); // Створення ref const onButtonClick = () => { // current вказує на змонтований DOM-елемент inputEl.current.focus(); }; return ( <> <input ref={inputEl} type="text" /> // Прив'язка ref <button onClick={onButtonClick}>Фокус на полі вводу</button> </> ); } -
useImperativeHandle: Налаштовує дескриптор екземпляра, який надається батьківському компоненту при використанніref. Дозволяє дочірньому компоненту розкривати певні методи батьківському компоненту. Використовується у спільній роботі зforwardRef.// Приклад useImperativeHandle import React, { useRef, useImperativeHandle, forwardRef } from 'react'; const MyInput = forwardRef((props, ref) => { const inputRef = useRef(); useImperativeHandle(ref, () => ({ focusInput: () => { inputRef.current.focus(); } })); return <input ref={inputRef} {...props} />; }); function ParentComponent() { const inputRef = useRef(); const handleFocus = () => { inputRef.current.focusInput(); // Виклик методу з дочірнього компонента }; return ( <div> <MyInput ref={inputRef} /> <button onClick={handleFocus}>Фокус через Parent</button> </div> ); } -
useLayoutEffect: ІдентичнийuseEffect, але виконується синхронно після всіх мутацій DOM. Корисний для читання даних з DOM або виконання мутацій, які потрібно зробити до того, як браузер перерисує екран. Може блокувати рендеринг.// Приклад useLayoutEffect import React, { useLayoutEffect, useRef } from 'react'; function Tooltip({ children, text }) { const ref = useRef(null); useLayoutEffect(() => { if (ref.current) { // Обчислення на основі DOM перед перерисовкою const { top, height } = ref.current.getBoundingClientRect(); console.log(`Елемент знаходиться на ${top} з висотою ${height}`); } }, [children]); return ( <span ref={ref} title={text}> {children} </span> ); } -
useDebugValue: Відображає користувацьку мітку для хуків у React DevTools. Використовується у користувацьких хуках для відлагодження.// Приклад useDebugValue import React, { useState, useDebugValue } from 'react'; function useFriendStatus(friendID) { const [isOnline, setIsOnline] = useState(null); // Відображає 'Friend Status: Offline' або 'Friend Status: Online' у DevTools useDebugValue(isOnline === true ? 'Online' : 'Offline'); // ... логіка отримання статусу друга return isOnline; } function FriendListItem({ friend }) { const isOnline = useFriendStatus(friend.id); return ( <li style={{ color: isOnline ? 'green' : 'black' }}> {friend.name} - {isOnline ? 'Онлайн' : 'Офлайн'} </li> ); }
Крім вбудованих хуків, існують також користувацькі хуки (Custom Hooks). Це JavaScript-функції, імена яких починаються з "use". Вони дозволяють повторно використовувати логіку стану між компонентами. Користувацький хук може викликати інші хуки.
// Приклад користувацького хука
import { useState, useEffect } from 'react';
function useWindowSize() {
const [size, setSize] = useState([window.innerWidth, window.innerHeight]);
useEffect(() => {
const handleResize = () => {
setSize([window.innerWidth, window.innerHeight]);
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
return size;
}
function MyComponent() {
const [width, height] = useWindowSize(); // Використання користувацького хука
return (
<p>Розмір вікна: {width}x{height}</p>
);
}
Важливо дотримуватися Правил хуків:
- Викликайте хуки лише на верхньому рівні компонента React або користувацького хука. Не викликайте їх всередині циклів, умов або вкладених функцій.
- Викликайте хуки лише з функціональних компонентів React або користувацьких хуків. Не викликайте їх з звичайних JavaScript-функцій або методів класових компонентів.