Sobes.tech
Junior

Millised on hook'id Reactis?

sobes.tech AI

Vastus AI-lt

Alates Reacti versioonist 16.8 pakuvad hookid funktsionaalsetelele komponentidele võimalust hallata olekut ja kasutada elutsükleid, mis varem olid saadaval ainult klassikomponentidele.

Siin on peamised sisseehitatud hookid:

  • useState: võimaldab lisada sisemist olekut funktsionaalsele komponendile. Tagastab paari: praeguse oleku ja funktsiooni selle uuendamiseks.

    // `useState` näide
    import React, { useState } from 'react';
    
    function Counter() {
      const [count, setCount] = useState(0); // Oleku initsialiseerimine 0-ga
    
      return (
        <div>
          <p>Olete klõpsanud {count} korda</p>
          <button onClick={() => setCount(count + 1)}>
            Klõpsa mind
          </button>
        </div>
      );
    }
    
  • useEffect: võimaldab täita kõrvaltoimeid funktsionaalsetes komponentides. Sarnane klasside elutsükli meetoditega (componentDidMount, componentDidUpdate, componentWillUnmount).

    // `useEffect` näide
    import React, { useState, useEffect } from 'react';
    
    function Example() {
      const [count, setCount] = useState(0);
    
      // käivitub iga renderi järel
      useEffect(() => {
        document.title = `Olete klõpsanud ${count} korda`;
      });
    
      // käivitub ainult esimesel renderil (tühi sõltuvuste massiiv)
      useEffect(() => {
        console.log('Komponent on monteeritud');
        return () => {
          console.log('Komponent on demonteeritud'); // puhastusfunktsioon
        };
      }, []);
    
      // käivitub, kui muutub count
      useEffect(() => {
        console.log('Count muutus:', count);
      }, [count]);
    
      return (
        <div>
          <p>Olete klõpsanud {count} korda</p>
          <button onClick={() => setCount(count + 1)}>
            Klõpsa mind
          </button>
        </div>
      );
    }
    
  • useContext: võimaldab registreeruda React konteksti muutustele. Võtab vastu konteksti objekti, mis on loodud React.createContext() abil.

    // `useContext` näide
    import React, { useContext } from 'react';
    
    const ThemeContext = React.createContext('light'); // Konteksti loomine
    
    function ThemedButton() {
      const theme = useContext(ThemeContext); // Konteksti kasutamine
    
      return (
        <button className={theme}>
          Nupp teemas {theme}
        </button>
      );
    }
    
    function App() {
      return (
        <ThemedButton />
      );
    }
    
  • useReducer: alternatiiv useState keerulisema oleku haldamiseks, mis hõlmab mitut alamolekut või kui järgmine olek sõltub eelmisest. Sarnane Redux reduceritele.

    // `useReducer` näide
    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 (
        <>
          Arv: {state.count}
          <button onClick={() => dispatch({ type: 'increment' })}>+</button>
          <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
        </>
      );
    }
    
  • useCallback: memoiseerib tagasikutsumise funktsiooni. Tagastab memoiseeritud versiooni, mis muutub ainult sõltuvuste muutumisel. Kasulik, et vältida tarbetuid lapsekomponentide uuesti renderdusi funktsioonide edastamisel.

    // `useCallback` näide
    import React, { useState, useCallback } from 'react';
    
    function Parent({ addTodo }) {
      const [count, setCount] = useState(0);
    
      const handleAddTodo = useCallback(() => {
        addTodo();
      }, [addTodo]); // sõltuvus addTodo-st
    
      return (
        <>
          <button onClick={() => setCount(count + 1)}>
            Suurenda arvu
          </button>
          <Child onAddItem={handleAddTodo} />
        </>
      );
    }
    
    function Child({ onAddItem }) {
      console.log('Lapsekomponent renderdatakse'); // renderdatakse ainult, kui muutub onAddItem
      return <button onClick={onAddItem}>Lisa element</button>;
    }
    
  • useMemo: memoiseerib arvutatud väärtuse. Tagastab memoiseeritud väärtuse, mis arvutatakse ainult sõltuvuste muutumisel. Kasulik jõudluse parandamiseks keerulistes arvutustes.

    // `useMemo` näide
    import React, { useMemo, useState } from 'react';
    
    function expensiveCalculation(num) {
      console.log('Kallid arvutused käivitatud...');
      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]); // sõltuvus count-st
    
      const addTodo = () => {
        setTodos(t => [...t, "Uus ülesanne"]);
      };
    
      return (
        <div>
          <div>
            <h2>Minu ülesanded</h2>
            {todos.map((todo, index) => (
              <p key={index}>{todo}</p>
            ))}
            <button onClick={addTodo}>Lisa ülesanne</button>
          </div>
          <hr />
          <div>
            Arv: {count}
            <button onClick={() => setCount(c => c + 1)}>+</button>
            <h2>Kallid arvutused</h2>
            {calculation}
          </div>
        </div>
      );
    }
    
  • useRef: võimaldab luua muudetava viite, mis säilib kogu komponendi elutsükli jooksul. Sageli kasutatakse DOM elementidele juurdepääsuks või mis tahes muudetava väärtuse hoidmiseks, mis ei põhjusta uuesti renderdamist.

    // `useRef` näide
    import React, { useRef } from 'react';
    
    function TextInputWithFocusButton() {
      const inputEl = useRef(null); // viite loomine
    
      const onButtonClick = () => {
        // current viitab DOM elemendile
        inputEl.current.focus();
      };
    
      return (
        <>
          <input ref={inputEl} type="text" /> // viite sidumine
          <button onClick={onButtonClick}>Fookus sisendväljal</button>
        </>
      );
    }
    
  • useImperativeHandle: konfigureerib eksemplari kirjelduse, mis edastatakse vanemkomponendile ref kaudu. Annab lapsekomponendile võimaluse avaldada teatud meetodeid vanemkomponendile. Kasutatakse koos forwardRef.

    // `useImperativeHandle` näide
    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(); // lapsekomponendi meetodi väljakutse
      };
    
      return (
        <div>
          <MyInput ref={inputRef} />
          <button onClick={handleFocus}>Fookus vanemast</button>
        </div>
      );
    }
    
  • useLayoutEffect: sarnane useEffect'ile, kuid täidetakse sünkroniseeritult pärast kõiki DOM-i mutatsioone. Kasulik DOM-ist andmete lugemiseks või mutatsioonide tegemiseks enne ekraani uuendamist. Võib blokeerida renderdamise.

    // `useLayoutEffect` näide
    import React, { useLayoutEffect, useRef } from 'react';
    
    function Tooltip({ children, text }) {
      const ref = useRef(null);
    
      useLayoutEffect(() => {
        if (ref.current) {
          // arvutused DOM-i põhjal enne uuendamist
          const { top, height } = ref.current.getBoundingClientRect();
          console.log(`Element asub ${top} positsioonil, kõrgus ${height}`);
        }
      }, [children]);
    
      return (
        <span ref={ref} title={text}>
          {children}
        </span>
      );
    }
    
  • useDebugValue: kuvab kasutaja märgise React DevTools'is. Kasutatakse oma hook'ide silumiseks.

    // `useDebugValue` näide
    import React, { useState, useDebugValue } from 'react';
    
    function useFriendStatus(friendID) {
      const [isOnline, setIsOnline] = useState(null);
    
      // kuvab "Friend Status: Offline" või "Friend Status: Online" DevTools'is
      useDebugValue(isOnline === true ? 'Online' : 'Offline');
    
      // ... sõbra staatuse saamise loogika
    
      return isOnline;
    }
    
    function FriendListItem({ friend }) {
      const isOnline = useFriendStatus(friend.id);
    
      return (
        <li style={{ color: isOnline ? 'green' : 'black' }}>
          {friend.name} - {isOnline ? 'Online' : 'Offline'}
        </li>
      );
    }
    

Lisaks sisseehitatud hookidele on olemas ka kasutaja defineeritud hook'id (Custom Hooks). Need on JavaScripti funktsioonid, mille nimed algavad "use". Need võimaldavad taaskasutada oleku loogikat komponentide vahel. Kasutaja defineeritud hook võib kutsuda teisi hook'e.

// Kasutaja defineeritud hook'i näide
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(); // kasutades kasutaja defineeritud hook'i

  return (
    <p>Akna suurus: {width}x{height}</p>
  );
}

Oluline on järgida hook'ide reegleid:

  1. Kutsuge hook'e ainult Reacti funktsionaalsete komponentide või kasutaja defineeritud hook'ide sees. Ärge kutsuge neid tsüklites, tingimustes või sisemistes funktsioonides.
  2. Kutsuge hook'e ainult Reacti funktsionaalsetest komponentidest või kasutaja hook'idest. Ärge kutsuge neid tavalistest JavaScripti funktsioonidest või klassi meetoditest.