Aké sú hooky v Reacte?
sobes.tech AI
Odpoveď od AI
V Reacte, od verzie 16.8, hooky poskytujú funkčným komponentám možnosť spravovať stav a využívať životné cykly, ktoré boli predtým dostupné iba v triednych komponentách.
Tu sú základné vstavané hooky:
-
useState: Umožňuje pridať vnútorný stav k funkčnej komponentu. Vráti pár: aktuálny stav a funkciu na jeho aktualizáciu.// Príklad useState import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); // Inicializácia stavu s 0 return ( <div> <p>Stlačili ste {count} krát</p> <button onClick={() => setCount(count + 1)}> Stlač ma </button> </div> ); } -
useEffect: Umožňuje vykonávať vedľajšie efekty v funkčných komponentoch. Podobné metódam životného cyklu triednych komponentov (componentDidMount,componentDidUpdate,componentWillUnmount).// Príklad useEffect import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // Spúšťa sa po každom renderi useEffect(() => { document.title = `Stlačili ste ${count} krát`; }); // Spúšťa sa iba pri prvom renderi (prázdne pole závislostí) useEffect(() => { console.log('Komponenta je namontovaná'); return () => { console.log('Komponenta je odmontovaná'); // Funkcia na vyčistenie }; }, []); // Spúšťa sa pri zmene count useEffect(() => { console.log('Count sa zmenil:', count); }, [count]); return ( <div> <p>Stlačili ste {count} krát</p> <button onClick={() => setCount(count + 1)}> Stlač ma </button> </div> ); } -
useContext: Umožňuje prihlásiť sa na zmeny kontextu Reactu. Prijíma objekt kontextu, vytvorený pomocouReact.createContext().// Príklad useContext import React, { useContext } from 'react'; const ThemeContext = React.createContext('light'); // Vytvorenie kontextu function ThemedButton() { const theme = useContext(ThemeContext); // Použitie kontextu return ( <button className={theme}> Tlačidlo v téme {theme} </button> ); } function App() { return ( <ThemedButton /> ); } -
useReducer: Alternatíva kuseStatena riadenie zložitejšieho stavu, ktorý zahŕňa niekoľko podhodnôt alebo keď nasledujúci stav závisí od predchádzajúceho. Podobné reducerom v Redux.// Príklad 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 ( <> Počet: {state.count} <button onClick={() => dispatch({ type: 'increment' })}>+</button> <button onClick={() => dispatch({ type: 'decrement' })}>-</button> </> ); } -
useCallback: Memoizuje funkciu spätného volania. Vráti memoizovanú verziu callbacku, ktorá sa mení iba pri zmene jednej zo závislostí. Užitočné na zabránenie zbytočným rerenderom detských komponentov pri odovzdávaní callbackov.// Príklad useCallback import React, { useState, useCallback } from 'react'; function Parent({ addTodo }) { const [count, setCount] = useState(0); const handleAddTodo = useCallback(() => { addTodo(); }, [addTodo]); // Závislosť od addTodo return ( <> <button onClick={() => setCount(count + 1)}> Zvýšiť počítadlo </button> <Child onAddItem={handleAddTodo} /> </> ); } function Child({ onAddItem }) { console.log('Child sa renderuje'); // Bude sa renderovať iba pri zmene onAddItem return <button onClick={onAddItem}>Pridať položku</button>; } -
useMemo: Memoizuje vypočítanú hodnotu. Vráti memoizovanú hodnotu, ktorá sa prepočítava iba pri zmene jednej zo závislostí. Užitočné pre výkon pri náročných výpočtoch.// Príklad useMemo import React, { useMemo, useState } from 'react'; function expensiveCalculation(num) { console.log('Prebieha náročný výpočet...'); 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]); // Závislosť od count const addTodo = () => { setTodos(t => [...t, "Nový úloha"]); }; return ( <div> <div> <h2>Moje úlohy</h2> {todos.map((todo, index) => ( <p key={index}>{todo}</p> ))} <button onClick={addTodo}>Pridať úlohu</button> </div> <hr /> <div> Počet: {count} <button onClick={() => setCount(c => c + 1)}>+</button> <h2>Náročný výpočet</h2> {calculation} </div> </div> ); } -
useRef: Umožňuje vytvoriť mutabilný ref, ktorý sa zachová počas celého životného cyklu komponentu. Často sa používa na prístup k prvkom DOM alebo na uloženie akýchkoľvek mutabilných hodnôt, ktoré nevyvolávajú rerenderovanie pri zmene.// Príklad useRef import React, { useRef, useEffect } from 'react'; function TextInputWithFocusButton() { const inputEl = useRef(null); // Vytvorenie ref const onButtonClick = () => { // current ukazuje na namontovaný DOM prvok inputEl.current.focus(); }; return ( <> <input ref={inputEl} type="text" /> // Pripútanie ref <button onClick={onButtonClick}>Získať fokus na pole pre zadanie</button> </> ); } -
useImperativeHandle: Nastavuje descriptor inštancie, ktorý sa poskytuje rodičovskému komponentu pri použitíref. Umožňuje dieťaťu odhaliť určité metódy rodičovi. Používa sa v spolupráci sforwardRef.// Príklad 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(); // Volanie metódy z dieťaťa }; return ( <div> <MyInput ref={inputRef} /> <button onClick={handleFocus}>Získať fokus cez Parent</button> </div> ); } -
useLayoutEffect: Identický suseEffect, ale sa vykonáva synchronne po všetkých mutáciách DOM. Užitočný na čítanie dát z DOM alebo vykonávanie mutácií, ktoré je potrebné vykonať predtým, než prehliadač prekreslí obrazovku. Môže blokovať rendering.// Príklad useLayoutEffect import React, { useLayoutEffect, useRef } from 'react'; function Tooltip({ children, text }) { const ref = useRef(null); useLayoutEffect(() => { if (ref.current) { // Výpočty na základe DOM pred prekreslením const { top, height } = ref.current.getBoundingClientRect(); console.log(`Prvok sa nachádza na ${top} s výškou ${height}`); } }, [children]); return ( <span ref={ref} title={text}> {children} </span> ); } -
useDebugValue: Zobrazuje používateľskú značku pre hooky v React DevTools. Používa sa v vlastných hookoch na ladenie.// Príklad useDebugValue import React, { useState, useDebugValue } from 'react'; function useFriendStatus(friendID) { const [isOnline, setIsOnline] = useState(null); // Zobrazuje 'Friend Status: Offline' alebo 'Friend Status: Online' v DevTools useDebugValue(isOnline === true ? 'Online' : 'Offline'); // ... logika získavania stavu kamaráta return isOnline; } function FriendListItem({ friend }) { const isOnline = useFriendStatus(friend.id); return ( <li style={{ color: isOnline ? 'green' : 'black' }}> {friend.name} - {isOnline ? 'Online' : 'Offline'} </li> ); }
Okrem vstavaných hookov existujú aj vlastné hooky (Custom Hooks). Ide o JavaScriptové funkcie, ktorých názvy začínajú s "use". Umožňujú opakovane používať logiku stavu medzi komponentami. Vlastný hook môže volať iné hooky.
// Príklad vlastného hooku
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(); // Použitie vlastného hooku
return (
<p>Veľkosť okna: {width}x{height}</p>
);
}
Dôležité je dodržiavať Pravidlá hookov:
- Volajte hooky iba na najvyššej úrovni React komponenty alebo vlastného hooku. Nevolajte ich vo vnútri cyklov, podmienok alebo vnorených funkcií.
- Volajte hooky iba z React funkčných komponent alebo vlastných hookov. Nevolajte ich z bežných JavaScriptových funkcií alebo metód triednych komponent.