Sobes.tech
Junior

რა hook-ები არსებობს React-ში?

sobes.tech AI

პასუხი AI-სგან

React-ში, 16.8 ვერსიიდან მოყოლებული, ჰუკები უზრუნველყოფს ფუნქციურ კომპონენტებს შესაძლებლობას მართონ მდგომარეობა და გამოიყენონ სიცოცხლის ციკლები, რომლებიც ადრე ხელმისაწვდომი იყო მხოლოდ კლასის კომპონენტებისთვის:

აქ არის ძირითადი ინტეგრირებული ჰუკები:

  • useState: საშუალებას აძლევს დაამატოთ შიდა მდგომარეობა ფუნქციურ კომპონენტს. ის აბრუნებს წყვილს: მიმდინარე მდგომარეობა და ფუნქცია მის განახლებისთვის:

    // useState მაგალითი
    import React, { useState } from 'react';
    
    function Counter() {
      const [count, setCount] = useState(0); // ინიციალიზაცია 0-ით
    
      return (
        <div>
          <p>თქვენ დაჭერით {count} ჯერ</p>
          <button onClick={() => setCount(count + 1)}>
            დაწკაპეთ მე
          </button>
        </div>
      );
    }
    
  • useEffect: საშუალებას აძლევს შეასრულოთ გვერდითი ეფექტები ფუნქციურ კომპონენტებში. მსგავსია კლასის სიცოცხლის ციკლის მეთოდების (componentDidMount, componentDidUpdate, componentWillUnmount):

    // useEffect მაგალითი
    import React, { useState, useEffect } from 'react';
    
    function Example() {
      const [count, setCount] = useState(0);
    
      // ხორციელდება ყოველი რენდერის შემდეგ
      useEffect(() => {
        document.title = `თქვენ დაჭერით ${count} ჯერ`;
      });
    
      // ხორციელდება მხოლოდ პირველ რენდერზე (ცარიელი დამოკიდებულებების მასივი)
      useEffect(() => {
        console.log('კომპონენტი მონტირებულია');
        return () => {
          console.log('კომპონენტი დუნეონტირებულია'); // სუფთავების ფუნქცია
        };
      }, []);
    
      // ხორციელდება count-ის ცვლილებაზე
      useEffect(() => {
        console.log('Count შეიცვალა:', count);
      }, [count]);
    
      return (
        <div>
          <p>თქვენ დაჭერით {count} ჯერ</p>
          <button onClick={() => setCount(count + 1)}>
            დაწკაპეთ მე
          </button>
        </div>
      );
    }
    
  • useContext: საშუალებას აძლევს გამოწეროთ React კონტექსტის ცვლილებებზე. იღებს კონტექსტის ობიექტს, რომელიც შექმნილია React.createContext()-ით:

    // useContext მაგალითი
    import React, { useContext } from 'react';
    
    const ThemeContext = React.createContext('light'); // კონტექსტის შექმნა
    
    function ThemedButton() {
      const theme = useContext(ThemeContext); // კონტექსტის გამოყენება
    
      return (
        <button className={theme}>
          ღილაკი თემაზე {theme}
        </button>
      );
    }
    
    function App() {
      return (
        <ThemedButton />
      );
    }
    
  • useReducer: ალტერნატივა useState-ს უფრო რთული მდგომარეობის მართვისთვის, რომელიც მოიცავს რამდენიმე ქვემდგომ მნიშვნელობას ან როდესაც შემდეგი მდგომარეობა დამოკიდებულია წინამორბედზე. მსგავსია Redux-ის რედიუსერების:

    // 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 (
        <>
          <p>გამომთვლელი: {state.count}</p>
          <button onClick={() => dispatch({ type: 'increment' })}>+</button>
          <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
        </>
      );
    }
    
  • useCallback: მემოიზირებს callback ფუნქციას. აბრუნებს მემოიზირებულ ვერსიას, რომელიც იცვლება მხოლოდ დამოკიდებულებების ცვლილებისას. სასარგებლოა არასაჭირო რენდერების თავიდან აცილებისთვის:

    // useCallback მაგალითი
    import React, { useState, useCallback } from 'react';
    
    function Parent({ addTodo }) {
      const [count, setCount] = useState(0);
    
      const handleAddTodo = useCallback(() => {
        addTodo();
      }, [addTodo]); // დამოკიდებულება addTodo-ზე
    
      return (
        <>
          <button onClick={() => setCount(count + 1)}>
            გამრავლე გამოთვლითი
          </button>
          <Child onAddItem={handleAddTodo} />
        </>
      );
    }
    
    function Child({ onAddItem }) {
      console.log('Child რენდდება'); // მხოლოდ მაშინ, როდესაც იცვლება onAddItem
      return <button onClick={onAddItem}>პარამეტრის დამატება</button>;
    }
    
  • useMemo: მემოიზირებს გამოთვლას. აბრუნებს მემოიზირებულ მნიშვნელობას, რომელიც გადათვლილია მხოლოდ დამოკიდებულებების ცვლილებისას. სასარგებლოა ძვირადღირებული გამოთვლებისთვის:

    // useMemo მაგალითი
    import React, { useMemo, useState } from 'react';
    
    function expensiveCalculation(num) {
      console.log('ძვირადღირებული გამოთვლა მიმდინარეობს...');
      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]); // დამოკიდებულება count-ზე
    
      const addTodo = () => {
        setTodos(t => [...t, "ახალი Todo"]);
      };
    
      return (
        <div>
          <div>
            <h2>ჩემი Todo-ები</h2>
            {todos.map((todo, index) => (
              <p key={index}>{todo}</p>
            ))}
            <button onClick={addTodo}>Todo დამატება</button>
          </div>
          <hr />
          <div>
            გამოთვლილი: {count}
            <button onClick={() => setCount(c => c + 1)}>+</button>
            <h2>ძვირადღირებული გამოთვლა</h2>
            {calculation}
          </div>
        </div>
      );
    }
    
  • useRef: საშუალებას აძლევს შექმნათ მუტაბელი რეფი, რომელიც ინახება მთელი კომპონენტის სიცოცხლის ციკლში. ხშირად გამოიყენება DOM ელემენტებზე წვდომისთვის ან ნებისმიერი მუტაბელი მნიშვნელობის შენახვისთვის, რომელიც არ იწვევს რენდერებს:

    // useRef მაგალითი
    import React, { useRef } from 'react';
    
    function TextInputWithFocusButton() {
      const inputEl = useRef(null); // რეფის შექმნა
    
      const onButtonClick = () => {
        // current მიუთითებს მონტაჟირებულ DOM ელემენტზე
        inputEl.current.focus();
      };
    
      return (
        <>
          <input ref={inputEl} type="text" /> // რეფის დაკავშირება
          <button onClick={onButtonClick}>ფოკუსის გადაცემა</button>
        </>
      );
    }
    
  • useImperativeHandle: კონფიგურირებს მაგალითის დესკრიპტორს, რომელიც ხელმისაწვდომია მშობელ კომპონენტისთვის ref-ის საშუალებით. საშუალებას აძლევს შვილს გამოაცხადოს გარკვეული მეთოდები მშობელს:

    // 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(); // შვილიდან მეთოდის გამოძახება
      };
    
      return (
        <div>
          <MyInput ref={inputRef} />
          <button onClick={handleFocus}>ფოკუსის გადაცემა</button>
        </div>
      );
    }
    
  • useLayoutEffect: იგივეა, რაც useEffect, მაგრამ სინქრონულად შესრულდება ყველა DOM მუტაციის შემდეგ, სანამ ბრაუზერი განაახლებს ეკრანს. სასარგებლოა DOM-დან მონაცემების წაკითხვასა და მუტაციებისთვის, რომლებიც უნდა შესრულდეს სანამ ეკრანი განახლდება:

    // useLayoutEffect მაგალითი
    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(`ელემენტი მდებარეობს ${top} სიმაღლეზე, სიმაღლე: ${height}`);
        }
      }, [children]);
    
      return (
        <span ref={ref} title={text}>
          {children}
        </span>
      );
    }
    
  • useDebugValue: აჩვენებს მომხმარებლის ნიშანს React DevTools-ში ჰუკებისთვის:

    // useDebugValue მაგალითი
    import React, { useState, useDebugValue } from 'react';
    
    function useFriendStatus(friendID) {
      const [isOnline, setIsOnline] = useState(null);
    
      useDebugValue(isOnline === true ? 'ონლაინ' : 'გათიშული');
    
      // ... მეგობრის სტატუსის მიღების ლოგიკა
    
      return isOnline;
    }
    
    function FriendListItem({ friend }) {
      const isOnline = useFriendStatus(friend.id);
    
      return (
        <li style={{ color: isOnline ? 'მწვანე' : 'შავი' }}>
          {friend.name} - {isOnline ? 'ონლაინ' : 'გათიშული'}
        </li>
      );
    }
    

გარდა ინტეგრირებული ჰუკების, არსებობს მომხმარებლის ჰუკები (Custom Hooks). ეს არის JavaScript ფუნქციები, რომელთა სახელები იწყება "use":

// მომხმარებლის ჰუკის მაგალითი
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(); // გამოყენება მომხმარებლის ჰუკის

  return (
    <p>ფანჯრის ზომა: {width}x{height}</p>
  );
}

მნიშვნელოვანია დაცვა ჰუკების გამოყენების წესებს:

  1. გამოიყენეთ ჰუკები მხოლოდ React-ის ფუნქციურ კომპონენტში ან მომხმარებლის ჰუკში, ზედა დონეზე. არ გამოიყენოთ ციკლებში, პირობით ან შიგნით ფუნქციებში.
  2. გამოიყენეთ ჰუკები მხოლოდ React-ის ფუნქციურ კომპონენტებიდან ან მომხმარებლის ჰუკებიდან. არ გამოიყენოთ ჩვეულებრივ JavaScript ფუნქციებიდან ან კლასის კომპონენტების მეთოდებიდან.