Sobes.tech
Junior

Milyen hookok vannak a React-ben?

sobes.tech MI

Válasz az MI-től

A Reactben, a 16.8-as verziótól kezdve a hookok lehetővé teszik a funkcionális komponensek számára az állapotkezelést és az életciklusok használatát, amelyek korábban csak osztályos komponensek számára voltak elérhetők.

Íme a fő beépített hookok:

  • useState: Lehetővé teszi egy belső állapot hozzáadását a funkcionális komponenshez. Visszaad egy párt: a jelenlegi állapotot és egy függvényt az állapot frissítéséhez.

    // useState példa
    import React, { useState } from 'react';
    
    function Counter() {
      const [count, setCount] = useState(0); // Állapot inicializálása 0-ra
    
      return (
        <div>
          <p>Összesen {count} alkalommal kattintottál</p>
          <button onClick={() => setCount(count + 1)}>
            Kattints rám
          </button>
        </div>
      );
    }
    
  • useEffect: Lehetővé teszi mellékhatások végrehajtását funkcionális komponensekben. Hasonló a class életciklus módszereihez (componentDidMount, componentDidUpdate, componentWillUnmount).

    // useEffect példa
    import React, { useState, useEffect } from 'react';
    
    function Example() {
      const [count, setCount] = useState(0);
    
      // Minden render után fut
      useEffect(() => {
        document.title = `Összesen kattintottál ${count} alkalommal`;
      });
    
      // Csak az első render után fut (üres függőségi tömb)
      useEffect(() => {
        console.log('A komponens fel van töltve');
        return () => {
          console.log('A komponens eltávolítva'); // Tisztító függvény
        };
      }, []);
    
      // Akkor fut, amikor a count változik
      useEffect(() => {
        console.log('A count változott:', count);
      }, [count]);
    
      return (
        <div>
          <p>Összesen {count} alkalommal kattintottál</p>
          <button onClick={() => setCount(count + 1)}>
            Kattints rám
          </button>
        </div>
      );
    }
    
  • useContext: Lehetővé teszi a React kontextus változásaira való feliratkozást. A React.createContext() segítségével létrehozott kontextus objektumot fogadja el.

    // useContext példa
    import React, { useContext } from 'react';
    
    const ThemeContext = React.createContext('light'); // Kontextus létrehozása
    
    function ThemedButton() {
      const theme = useContext(ThemeContext); // Kontextus használata
    
      return (
        <button className={theme}>
          Gomb a {theme} témában
        </button>
      );
    }
    
    function App() {
      return (
        <ThemedButton />
      );
    }
    
  • useReducer: Alternatíva a useState-hez a bonyolultabb állapotkezeléshez, amely több al-értéket tartalmaz vagy amikor a következő állapot a korábbi függvénye. Hasonló a Redux redukereihez.

    // useReducer példa
    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: Memóriahelyezi a visszahívási függvényt. Csak akkor változik, ha egy függőség megváltozik. Hasznos a felesleges újrarenderelések elkerülésében, amikor gyermekkomponenseknek adunk át callbackeket.

    // useCallback példa
    import React, { useState, useCallback } from 'react';
    
    function Parent({ addTodo }) {
      const [count, setCount] = useState(0);
    
      const handleAddTodo = useCallback(() => {
        addTodo();
      }, [addTodo]); // függőség: addTodo
    
      return (
        <>
          <button onClick={() => setCount(count + 1)}>
            Számláló növelése
          </button>
          <Child onAddItem={handleAddTodo} />
        </>
      );
    }
    
    function Child({ onAddItem }) {
      console.log('Child újrarenderelése'); // Csak akkor renderelődik újra, ha az onAddItem változik
      return <button onClick={onAddItem}>Elem hozzáadása</button>;
    }
    
  • useMemo: Memóriahelyezi a számított értéket. Csak akkor számítja újra, ha egy függőség megváltozik. Hasznos a drága számítások optimalizálásához.

    // useMemo példa
    import React, { useMemo, useState } from 'react';
    
    function expensiveCalculation(num) {
      console.log('Drága számítás fut');
      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]); // függőség: count
    
      const addTodo = () => {
        setTodos(t => [...t, "Új teendő"]);
      };
    
      return (
        <div>
          <div>
            <h2>Teendőim</h2>
            {todos.map((todo, index) => (
              <p key={index}>{todo}</p>
            ))}
            <button onClick={addTodo}>Teendő hozzáadása</button>
          </div>
          <hr />
          <div>
            Szám: {count}
            <button onClick={() => setCount(c => c + 1)}>+</button>
            <h2>Drága számítás</h2>
            {calculation}
          </div>
        </div>
      );
    }
    
  • useRef: Lehetővé teszi egy mutálható referencia létrehozását, amely az egész komponens életciklusa alatt megmarad. Gyakran használják DOM elemekhez való hozzáféréshez vagy bármilyen mutálható érték tárolásához, amely nem vált ki újrarenderelést.

    // useRef példa
    import React, { useRef } from 'react';
    
    function TextInputWithFocusButton() {
      const inputEl = useRef(null); // referencia létrehozása
    
      const onButtonClick = () => {
        inputEl.current.focus(); // DOM elem fókuszálása
      };
    
      return (
        <>
          <input ref={inputEl} type="text" /> // referencia kötése
          <button onClick={onButtonClick}>Fókusz a szövegmezőn</button>
        </>
      );
    }
    
  • useImperativeHandle: Beállítja az példány leíróját, amelyet a szülő komponens a ref használatával ér el. Lehetővé teszi a gyermekkomponens számára, hogy bizonyos metódusokat tegyen elérhetővé a szülő számára. A forwardRef-el együtt használják.

    // useImperativeHandle példa
    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(); // gyermek komponens metódusának hívása
      };
    
      return (
        <div>
          <MyInput ref={inputRef} />
          <button onClick={handleFocus}>Fókusz a szülőtől</button>
        </div>
      );
    }
    
  • useLayoutEffect: Hasonló a useEffect-hez, de szinkron módon fut le minden DOM módosítás után, mielőtt a böngésző újrarajzolná a képernyőt. Hasznos DOM-ból való olvasáshoz vagy módosításokhoz, amelyeknek a render előtt kell megtörténniük. Megakadályozhatja a renderelést.

    // useLayoutEffect példa
    import React, { useLayoutEffect, useRef } from 'react';
    
    function Tooltip({ children, text }) {
      const ref = useRef(null);
    
      useLayoutEffect(() => {
        if (ref.current) {
          const { top, height } = ref.current.getBoundingClientRect();
          console.log(`Az elem ${top} helyen van, magassága ${height}`);
        }
      }, [children]);
    
      return (
        <span ref={ref} title={text}>
          {children}
        </span>
      );
    }
    
  • useDebugValue: Megjeleníti a felhasználó által definiált címkét a React DevTools-ban. Használható egyéni hookok hibakereséséhez.

    // useDebugValue példa
    import React, { useState, useDebugValue } from 'react';
    
    function useFriendStatus(friendID) {
      const [isOnline, setIsOnline] = useState(null);
    
      // A DevTools-ban "Friend Status: Offline" vagy "Friend Status: Online" jelenik meg
      useDebugValue(isOnline === true ? 'Online' : 'Offline');
    
      // ... a barát státuszának lekérdezése
    
      return isOnline;
    }
    
    function FriendListItem({ friend }) {
      const isOnline = useFriendStatus(friend.id);
    
      return (
        <li style={{ color: isOnline ? 'zöld' : 'fekete' }}>
          {friend.name} - {isOnline ? 'Online' : 'Offline'}
        </li>
      );
    }
    

A beépített hookokon kívül léteznek egyéni hookok is. Ezek JavaScript függvények, amelyek nevei "use"-vel kezdődnek. Lehetővé teszik az állapotkezelési logika újrafelhasználását a komponensek között. Egy egyéni hook más hookokat is hívhat.

// Egyéni hook példa
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(); // egyéni hook használata

  return (
    <p>A böngésző mérete: {width}x{height}</p>
  );
}

Fontos szabályok a hookok használatára:

  1. Csak a React komponensek vagy egyéni hookok tetején hívjon hookokat. Ne hívja őket ciklusokban, feltételekben vagy belső függvényekben.
  2. Csak funkcionális komponensekből vagy egyéni hookokból hívja őket. Ne hívja őket sima JavaScript függvényekből vagy osztályos komponensek metódusaiból.