Sobes.tech
Junior

Kādi ir hook'i React?

sobes.tech AI

Atbilde no AI

No React 16.8 versijas hook'ai sniedz funkcionalajiem komponentiem iespēju pārvaldīt stāvokli un izmantot dzīves ciklus, kas agrāk bija pieejami tikai klases komponentiem.

Šeit ir galvenie iebūvētie hook'i:

  • useState: ļauj pievienot iekšējo stāvokli funkcionalajam komponentam. Atgriež pāri: pašreizējo stāvokli un funkciju to atjaunināšanai.

    // `useState` piemērs
    import React, { useState } from 'react';
    
    function Counter() {
      const [count, setCount] = useState(0); // Stāvokļa inicializācija ar 0
    
      return (
        <div>
          <p>Jūs nospiedāt {count} reizes</p>
          <button onClick={() => setCount(count + 1)}>
            Nospiediet mani
          </button>
        </div>
      );
    }
    
  • useEffect: ļauj veikt blakus efektus funkcionalajos komponentos. Līdzīgs klases dzīves cikla metodēm (componentDidMount, componentDidUpdate, componentWillUnmount).

    // `useEffect` piemērs
    import React, { useState, useEffect } from 'react';
    
    function Example() {
      const [count, setCount] = useState(0);
    
      // izpildās pēc katra renderēšanas
      useEffect(() => {
        document.title = `Jūs nospiedāt ${count} reizes`;
      });
    
      // izpildās tikai pirmajā renderēšanā (tukšs atkarību masīvs)
      useEffect(() => {
        console.log('Komponents ielādēts');
        return () => {
          console.log('Komponents noņemts'); // tīrīšanas funkcija
        };
      }, []);
    
      // izpildās, kad mainās count
      useEffect(() => {
        console.log('Count mainījās:', count);
      }, [count]);
    
      return (
        <div>
          <p>Jūs nospiedāt {count} reizes</p>
          <button onClick={() => setCount(count + 1)}>
            Nospiediet mani
          </button>
        </div>
      );
    }
    
  • useContext: ļauj abonēt React konteksta izmaiņas. Pieņem konteksta objektu, kas izveidots ar React.createContext().

    // `useContext` piemērs
    import React, { useContext } from 'react';
    
    const ThemeContext = React.createContext('light'); // Konteksta izveide
    
    function ThemedButton() {
      const theme = useContext(ThemeContext); // Konteksta izmantošana
    
      return (
        <button className={theme}>
          Poga tēmas {theme}
        </button>
      );
    }
    
    function App() {
      return (
        <ThemedButton />
      );
    }
    
  • useReducer: alternatīva useState sarežģītākas stāvokļa pārvaldībai, kas ietver vairākus apakšstāvokļus vai kad nākamais stāvoklis ir atkarīgs no iepriekšējā. Līdzīgs Redux reducera funkcijām.

    // `useReducer` piemērs
    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 (
        <>
          Skaits: {state.count}
          <button onClick={() => dispatch({ type: 'increment' })}>+</button>
          <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
        </>
      );
    }
    
  • useCallback: memoizē atgriešanas funkciju. Atgriež memoizētu funkcijas versiju, kas mainās tikai mainoties vienai no atkarībām. Noder, lai novērstu nevajadzīgas bērnu komponentu pārrenderēšanas, nododot funkcijas.

    // `useCallback` piemērs
    import React, { useState, useCallback } from 'react';
    
    function Parent({ addTodo }) {
      const [count, setCount] = useState(0);
    
      const handleAddTodo = useCallback(() => {
        addTodo();
      }, [addTodo]); // atkarība no addTodo
    
      return (
        <>
          <button onClick={() => setCount(count + 1)}>
            Palielināt skaitli
          </button>
          <Child onAddItem={handleAddTodo} />
        </>
      );
    }
    
    function Child({ onAddItem }) {
      console.log('Bērna komponents tiek renderēts'); // tiks renderēts tikai mainoties onAddItem
      return <button onClick={onAddItem}>Pievienot elementu</button>;
    }
    
  • useMemo: memoizē aprēķināto vērtību. Atgriež memoizētu vērtību, kas tiek pārskatīta tikai mainoties vienai no atkarībām. Noder veiktspējas uzlabošanai dārgiem aprēķiniem.

    // `useMemo` piemērs
    import React, { useMemo, useState } from 'react';
    
    function expensiveCalculation(num) {
      console.log('Veic dārgu aprēķinu...');
      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]); // atkarība no count
    
      const addTodo = () => {
        setTodos(t => [...t, "Jauns uzdevums"]);
      };
    
      return (
        <div>
          <div>
            <h2>Mani uzdevumi</h2>
            {todos.map((todo, index) => (
              <p key={index}>{todo}</p>
            ))}
            <button onClick={addTodo}>Pievienot uzdevumu</button>
          </div>
          <hr />
          <div>
            Skaitītājs: {count}
            <button onClick={() => setCount(c => c + 1)}>+</button>
            <h2>Dārgs aprēķins</h2>
            {calculation}
          </div>
        </div>
      );
    }
    
  • useRef: ļauj izveidot mainīgu atsauci, kas saglabājas visa komponenta dzīves cikla laikā. Bieži tiek izmantota, lai piekļūtu DOM elementiem vai glabātu jebkuru mainīgu vērtību, kas neizraisa pārrenderēšanu.

    // `useRef` piemērs
    import React, { useRef } from 'react';
    
    function TextInputWithFocusButton() {
      const inputEl = useRef(null); // atsauces izveide
    
      const onButtonClick = () => {
        // current norāda uz ielādēto DOM elementu
        inputEl.current.focus();
      };
    
      return (
        <>
          <input ref={inputEl} type="text" /> // atsauces pievienošana
          <button onClick={onButtonClick}>Fokusēt uz ievades lauku</button>
        </>
      );
    }
    
  • useImperativeHandle: konfigurē eksemplāra aprakstu, kas tiek nodots vecāku komponentam, izmantojot ref. Atļauj bērnu komponentam atklāt noteiktas metodes vecāku komponentam. Tiek izmantots kopā ar forwardRef.

    // `useImperativeHandle` piemērs
    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(); // metodes izsaukšana no bērnu komponenta
      };
    
      return (
        <div>
          <MyInput ref={inputRef} />
          <button onClick={handleFocus}>Fokusēt caur Parent</button>
        </div>
      );
    }
    
  • useLayoutEffect: identisks useEffect, bet tiek izpildīts sinhroni pēc visām DOM mutācijām. Noderīgs, lai lasītu datus no DOM vai veiktu mutācijas, kas ir jāveic pirms ekrāna atjaunināšanas. Var bloķēt renderēšanu.

    // `useLayoutEffect` piemērs
    import React, { useLayoutEffect, useRef } from 'react';
    
    function Tooltip({ children, text }) {
      const ref = useRef(null);
    
      useLayoutEffect(() => {
        if (ref.current) {
          // aprēķini, balstoties uz DOM pirms atjaunināšanas
          const { top, height } = ref.current.getBoundingClientRect();
          console.log(`Elements atrodas ${top} pozīcijā, augstums ${height}`);
        }
      }, [children]);
    
      return (
        <span ref={ref} title={text}>
          {children}
        </span>
      );
    }
    
  • useDebugValue: attēlo lietotāja marķējumu React DevTools. Tiek izmantots, veidojot savus hook'us, lai tos labotu.

    // `useDebugValue` piemērs
    import React, { useState, useDebugValue } from 'react';
    
    function useFriendStatus(friendID) {
      const [isOnline, setIsOnline] = useState(null);
    
      // attēlo "Friend Status: Offline" vai "Friend Status: Online" DevTools
      useDebugValue(isOnline === true ? 'Online' : 'Offline');
    
      // ... loģika, kā iegūt drauga statusu
    
      return isOnline;
    }
    
    function FriendListItem({ friend }) {
      const isOnline = useFriendStatus(friend.id);
    
      return (
        <li style={{ color: isOnline ? 'green' : 'black' }}>
          {friend.name} - {isOnline ? 'Online' : 'Offline'}
        </li>
      );
    }
    

Papildus iebūvētajiem hook'iem ir arī lietu pašu izveidoti hook'i (Custom Hooks). Tie ir JavaScript funkcijas, kuru nosaukumi sākas ar "use". Tie ļauj atkārtoti izmantot stāvokļa loģiku starp komponentiem. Lietotāja izveidots hook var izsaukt citus hook'us.

// Lietotāja izveidots hook piemērs
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(); // lietotāja hook

  return (
    <p>Loga izmērs: {width}x{height}</p>
  );
}

Svarīgi ievērot hook noteikumus:

  1. Izsauciet hook'us tikai React funkciju komponentu augšējā līmenī vai lietotāja hook'os. Neizsauciet to ciklos, nosacījumos vai iekšējās funkcijās.
  2. Izsauciet hook'us tikai no React funkciju komponentiem vai lietotāja hook'iem. Neizsauciet to no parastajām JavaScript funkcijām vai klases metodēm.