Ce hooks există în React?
sobes.tech AI
Răspuns de la AI
În React, începând cu versiunea 16.8, hooks oferă componentelor funcționale posibilitatea de a gestiona starea și de a utiliza ciclurile de viață, care anterior erau disponibile doar pentru componentele de clasă.
Iată principalele hooks încorporate:
-
useState: Permite adăugarea unei stări interne la o componentă funcțională. Returnează o pereche: starea curentă și o funcție pentru actualizarea acesteia.// Exemplu useState import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); // Inițializare stare cu 0 return ( <div> <p>Ați apăsat de {count} ori</p> <button onClick={() => setCount(count + 1)}> Apasă-mă </button> </div> ); } -
useEffect: Permite executarea efectelor secundare în componentele funcționale. Similar cu metodele de ciclul de viață ale componentelor de clasă (componentDidMount,componentDidUpdate,componentWillUnmount).// Exemplu useEffect import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // Se execută după fiecare randare useEffect(() => { document.title = `Ați apăsat ${count} ori`; }); // Se execută doar la prima randare (array de dependențe gol) useEffect(() => { console.log('Componenta a fost montată'); return () => { console.log('Componenta a fost demontată'); // Funcție de curățare }; }, []); // Se execută la schimbarea lui count useEffect(() => { console.log('Count a fost schimbat:', count); }, [count]); return ( <div> <p>Ați apăsat de {count} ori</p> <button onClick={() => setCount(count + 1)}> Apasă-mă </button> </div> ); } -
useContext: Permite abonarea la schimbările contextului React. Primește un obiect de context creat cuReact.createContext().// Exemplu useContext import React, { useContext } from 'react'; const ThemeContext = React.createContext('light'); // Crearea contextului function ThemedButton() { const theme = useContext(ThemeContext); // Utilizarea contextului return ( <button className={theme}> Buton în tema {theme} </button> ); } function App() { return ( <ThemedButton /> ); } -
useReducer: O alternativă lauseStatepentru gestionarea unui stări mai complexe, care implică mai multe sub-valori sau când următoarea stare depinde de cea anterioară. Similar cu reducerii din Redux.// Exemplu 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 ( <> Count: {state.count} <button onClick={() => dispatch({ type: 'increment' })}>+</button> <button onClick={() => dispatch({ type: 'decrement' })}>-</button> </> ); } -
useCallback: Memoizează o funcție de callback. Returnează o versiune memoizată a callback-ului, care se schimbă doar dacă se schimbă una dintre dependențe. Util pentru a preveni re-randări inutile ale componentelor copil atunci când se transmit callback-uri.// Exemplu useCallback import React, { useState, useCallback } from 'react'; function Parent({ addTodo }) { const [count, setCount] = useState(0); const handleAddTodo = useCallback(() => { addTodo(); }, [addTodo]); // Dependența de addTodo return ( <> <button onClick={() => setCount(count + 1)}> Crește contorul </button> <Child onAddItem={handleAddTodo} /> </> ); } function Child({ onAddItem }) { console.log('Componenta copil se re-randează'); // Se va re-randa doar dacă se schimbă onAddItem return <button onClick={onAddItem}>Adaugă element</button>; } -
useMemo: Memoizează o valoare calculată. Returnează o valoare memoizată, care se recalculază doar dacă se schimbă una dintre dependențe. Util pentru performanță în calcule costisitoare.// Exemplu useMemo import React, { useMemo, useState } from 'react'; function expensiveCalculation(num) { console.log('Se execută calculul costisitor...'); 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]); // Dependența de count const addTodo = () => { setTodos(t => [...t, "Todo nou"]); }; return ( <div> <div> <h2>Lista mea de Todo</h2> {todos.map((todo, index) => ( <p key={index}>{todo}</p> ))} <button onClick={addTodo}>Adaugă Todo</button> </div> <hr /> <div> Contor: {count} <button onClick={() => setCount(c => c + 1)}>+</button> <h2>Calcul costisitor</h2> {calculation} </div> </div> ); } -
useRef: Permite crearea unui ref mutabil, care persistă pe durata întregului ciclu de viață al componentului. Este adesea folosit pentru accesarea elementelor DOM sau pentru stocarea oricărei valori mutabile care nu provoacă re-randări la schimbare.// Exemplu useRef import React, { useRef } from 'react'; function TextInputWithFocusButton() { const inputEl = useRef(null); // Creare ref const onButtonClick = () => { // current indică elementul DOM montat inputEl.current.focus(); }; return ( <> <input ref={inputEl} type="text" /> // Atașare ref <button onClick={onButtonClick}>Focusează pe câmpul de input</button> </> ); } -
useImperativeHandle: Configurează descriptorul instanței, care este expus părintelui atunci când se foloseșteref. Permite componentului copil să dezvăluie anumite metode părintelui. Se folosește împreună cuforwardRef.// Exemplu 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(); // Apelarea metodei din componentul copil }; return ( <div> <MyInput ref={inputRef} /> <button onClick={handleFocus}>Focusează prin Parent</button> </div> ); } -
useLayoutEffect: Similar cuuseEffect, dar se execută sincron după toate mutațiile DOM. Util pentru citirea datelor din DOM sau efectuarea mutațiilor care trebuie să aibă loc înainte ca browserul să re-renderizeze ecranul. Poate bloca randarea.// Exemplu useLayoutEffect import React, { useLayoutEffect, useRef } from 'react'; function Tooltip({ children, text }) { const ref = useRef(null); useLayoutEffect(() => { if (ref.current) { // Calcul pe baza DOM înainte de re-render const { top, height } = ref.current.getBoundingClientRect(); console.log(`Elementul se află la ${top} cu înălțimea ${height}`); } }, [children]); return ( <span ref={ref} title={text}> {children} </span> ); } -
useDebugValue: Afișează o etichetă personalizată pentru hooks în React DevTools. Se folosește în hooks personalizate pentru depanare.// Exemplu useDebugValue import React, { useState, useDebugValue } from 'react'; function useFriendStatus(friendID) { const [isOnline, setIsOnline] = useState(null); // Afișează 'Stare prieten: Offline' sau 'Stare prieten: Online' în DevTools useDebugValue(isOnline === true ? 'Online' : 'Offline'); // ... logică pentru obținerea stării prietenului return isOnline; } function FriendListItem({ friend }) { const isOnline = useFriendStatus(friend.id); return ( <li style={{ color: isOnline ? 'green' : 'black' }}> {friend.name} - {isOnline ? 'Online' : 'Offline'} </li> ); }
Pe lângă hooks încorporate, există și hooks personalizate (Custom Hooks). Acestea sunt funcții JavaScript, ale căror nume încep cu "use". Permite reutilizarea logicii de stare între componente. Un hook personalizat poate apela alte hooks.
// Exemplu hook personalizat
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(); // Utilizare hook personalizat
return (
<p>Dimensiunea ferestrei: {width}x{height}</p>
);
}
Este important să respecți Regulile hooks:
- Apelarea hooks doar la nivelul de sus al componentelor React sau al hooks-urilor personalizate. Nu le apelați în interiorul buclelor, condițiilor sau funcțiilor în interior.
- Apelarea hooks doar din componente funcționale React sau hooks personalizate. Nu le apelați din funcții JavaScript obișnuite sau metode ale componentelor de clasă.