Koji su hookovi u Reactu?
sobes.tech АИ
Одговор од АИ
У 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: Омогућава креирање мутабилног реф-а који се чува током целог животног века компоненти. Често се користи за приступ елементима DOM или чување било које мутабилне вредности која не изазива поновно рендеровање при промени.// Пример useRef import React, { useRef, useEffect } from 'react'; function TextInputWithFocusButton() { const inputEl = useRef(null); // Креирање реф-а const onButtonClick = () => { // current указује на монтирани DOM елемент inputEl.current.focus(); }; return ( <> <input ref={inputEl} type="text" /> // Привезивање реф-а <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 функција или метода класних компоненти.