Kokie yra hook'ai React?
sobes.tech AI
Atsakymas iš AI
Nuo React 16.8 versijos, hook'ai suteikia funkciniams komponentams galimybę valdyti būseną ir naudoti gyvenimo ciklus, kurie anksčiau buvo prieinami tik klasių komponentams.
Štai pagrindiniai įmontuoti hook'ai:
-
useState: leidžia pridėti vidinę būseną funkciniam komponentui. Grąžina porą: esamą būseną ir funkciją ją atnaujinti.// `useState` pavyzdys import React, { useState } from 'react'; function Counter() { const [count, setCount] = useState(0); // Būsenos inicializavimas su 0 return ( <div> <p>Paspaudėte {count} kartus</p> <button onClick={() => setCount(count + 1)}> Spauskite mane </button> </div> ); } -
useEffect: leidžia vykdyti šalutinius efektus funkciniuose komponentuose. Panašus į klasių gyvenimo ciklo metodus (componentDidMount,componentDidUpdate,componentWillUnmount).// `useEffect` pavyzdys import React, { useState, useEffect } from 'react'; function Example() { const [count, setCount] = useState(0); // vykdomas po kiekvieno atvaizdavimo useEffect(() => { document.title = `Paspaudėte ${count} kartus`; }); // vykdomas tik pirmojo atvaizdavimo metu (tuščias priklausomybių masyvas) useEffect(() => { console.log('Komponentas įmontuotas'); return () => { console.log('Komponentas išmontuotas'); // valymo funkcija }; }, []); // vykdomas kai keičiasi count useEffect(() => { console.log('Count pasikeitė:', count); }, [count]); return ( <div> <p>Paspaudėte {count} kartus</p> <button onClick={() => setCount(count + 1)}> Spauskite mane </button> </div> ); } -
useContext: leidžia prenumeruoti React konteksto pokyčius. Priima konteksto objektą, sukurtą naudojantReact.createContext().// `useContext` pavyzdys import React, { useContext } from 'react'; const ThemeContext = React.createContext('light'); // Konteksto sukūrimas function ThemedButton() { const theme = useContext(ThemeContext); // Konteksto naudojimas return ( <button className={theme}> Mygtukas temoje {theme} </button> ); } function App() { return ( <ThemedButton /> ); } -
useReducer: alternatyvauseStatesudėtingesnei būsenos valdymui, apimančiai kelis subreikinius ar kai sekantis būsenos pokytis priklauso nuo ankstesnio. Panašus į Redux reducerius.// `useReducer` pavyzdys 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: memoizuoja atgalinio iškvietimo funkciją. Grąžina memoizuotą funkcijos versiją, kuri keičiasi tik pasikeitus vienai iš priklausomybių. Naudinga išvengti nereikalingo vaikų komponentų perperdavimo perduodant funkcijas.// `useCallback` pavyzdys import React, { useState, useCallback } from 'react'; function Parent({ addTodo }) { const [count, setCount] = useState(0); const handleAddTodo = useCallback(() => { addTodo(); }, [addTodo]); // priklausomybė nuo addTodo return ( <> <button onClick={() => setCount(count + 1)}> Padidinti skaičių </button> <Child onAddItem={handleAddTodo} /> </> ); } function Child({ onAddItem }) { console.log('Vaiko komponentas atvaizduojamas'); // bus atvaizduojamas tik pasikeitus onAddItem return <button onClick={onAddItem}>Pridėti elementą</button>; } -
useMemo: memoizuoja skaičiuojamą reikšmę. Grąžina memoizuotą reikšmę, kuri perperdaugia tik pasikeitus vienai iš priklausomybių. Naudinga našumui didelėms skaičiavimams.// `useMemo` pavyzdys import React, { useMemo, useState } from 'react'; function expensiveCalculation(num) { console.log('Vykdomas brangus skaičiavimas...'); 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]); // priklausomybė nuo count const addTodo = () => { setTodos(t => [...t, "Naujas užrašas"]); }; return ( <div> <div> <h2>Mano užrašai</h2> {todos.map((todo, index) => ( <p key={index}>{todo}</p> ))} <button onClick={addTodo}>Pridėti užrašą</button> </div> <hr /> <div> Skaičius: {count} <button onClick={() => setCount(c => c + 1)}>+</button> <h2>Brangus skaičiavimas</h2> {calculation} </div> </div> ); } -
useRef: leidžia sukurti keičiamą nuorodą, kuri išlieka viso komponento gyvavimo ciklo metu. Dažnai naudojama prieigos prie DOM elementų ar saugojimo bet kokios keičiamo vertės, kuri ne sukelia perperdavimų.// `useRef` pavyzdys import React, { useRef } from 'react'; function TextInputWithFocusButton() { const inputEl = useRef(null); // nuorodos sukūrimas const onButtonClick = () => { // current nurodo į įmontuotą DOM elementą inputEl.current.focus(); }; return ( <> <input ref={inputEl} type="text" /> // nuorodos priskyrimas <button onClick={onButtonClick}>Fokusuoti į įvesties lauką</button> </> ); } -
useImperativeHandle: konfigūruoja egzemplioriaus aprašą, kuris pateikiamas tėviniam komponentui naudojantref. Leidžia vaikų komponentui atskleisti tam tikras metodus tėviniam komponentui. Naudojama kartu suforwardRef.// `useImperativeHandle` pavyzdys 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(); // iš vaiko komponento iškviečiama metodo funkcija }; return ( <div> <MyInput ref={inputRef} /> <button onClick={handleFocus}>Fokusuoti per tėvą</button> </div> ); } -
useLayoutEffect: identiškasuseEffect, bet vykdomas sinchroniškai po visų DOM mutacijų. Naudinga skaityti duomenis iš DOM arba atlikti mutacijas, kurios turi būti padarytos prieš ekrano atnaujinimą. Gali blokuoti atvaizdavimą.// `useLayoutEffect` pavyzdys import React, { useLayoutEffect, useRef } from 'react'; function Tooltip({ children, text }) { const ref = useRef(null); useLayoutEffect(() => { if (ref.current) { // skaičiavimai remiantis DOM prieš atvaizdavimą const { top, height } = ref.current.getBoundingClientRect(); console.log(`Elementas yra ${top} pozicijoje, aukštis ${height}`); } }, [children]); return ( <span ref={ref} title={text}> {children} </span> ); } -
useDebugValue: rodo vartotojo žymę React DevTools. Naudojama kuriant savo hook'us, skirtus derinimui.// `useDebugValue` pavyzdys import React, { useState, useDebugValue } from 'react'; function useFriendStatus(friendID) { const [isOnline, setIsOnline] = useState(null); // rodo "Friend Status: Offline" arba "Friend Status: Online" DevTools useDebugValue(isOnline === true ? 'Online' : 'Offline'); // ... logika, kaip gauti draugo būseną return isOnline; } function FriendListItem({ friend }) { const isOnline = useFriendStatus(friend.id); return ( <li style={{ color: isOnline ? 'green' : 'black' }}> {friend.name} - {isOnline ? 'Online' : 'Offline'} </li> ); }
Be įmontuotų hook'ų, yra ir vartotojo sukurti hook'ai (Custom Hooks). Tai JavaScript funkcijos, kurių pavadinimai prasideda nuo "use". Jie leidžia pakartotinai naudoti būsenos logiką tarp komponentų. Vartotojo sukurtas hook'as gali kviesti kitus hook'us.
// Vartotojo sukurto hook'o pavyzdys
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(); // naudojamas vartotojo hook'as
return (
<p>Langas: {width}x{height}</p>
);
}
Svarbu laikytis hook'ų taisyklių:
- Naudokite hook'us tik aukšto lygio funkcijų komponentuose arba vartotojo hook'uose. Nenaudokite jų cikluose, sąlygose ar vidinėse funkcijose.
- Naudokite hook'us tik iš React funkcinių komponentų arba vartotojo hook'ų. Nenaudokite jų įprastose JavaScript funkcijose ar klasių metodų viduje.