← Назад к вопросам

Приведи примеры использования хуков

2.0 Middle🔥 162 комментариев
#JavaScript Core

Комментарии (2)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Примеры использования хуков в React

Хуки — это функции, которые позволяют использовать состояние и другие возможности React без написания классов. Они были добавлены в React 16.8 и стали стандартом для работы с состоянием,副作用 (side effects) и другими возможностями в функциональных компонентах. Вот ключевые примеры с пояснениями:

1. useState — работа с состоянием

useState позволяет добавить состояние в функциональный компонент. Он возвращает массив из двух элементов: текущее значение состояния и функцию для его обновления.

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0); // Инициализация состояния

  return (
    <div>
      <p>Вы нажали {count} раз</p>
      <button onClick={() => setCount(count + 1)}>
        Нажми меня
      </button>
      <button onClick={() => setCount(0)}>
        Сбросить
      </button>
    </div>
  );
}

2. useEffect — работа с побочными эффектами

useEffect позволяет выполнять побочные эффекты в функциональных компонентах: запросы к API, подписки, мануальные изменения DOM. Он заменяет методы жизненного цикла componentDidMount, componentDidUpdate и componentWillUnmount.

import React, { useState, useEffect } from 'react';

function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // Эта функция выполнится после каждого рендера,
    // если изменится userId (указано в массиве зависимостей)
    async function fetchUser() {
      setLoading(true);
      const response = await fetch(`/api/users/${userId}`);
      const data = await response.json();
      setUser(data);
      setLoading(false);
    }

    fetchUser();

    // Функция очистки (аналог componentWillUnmount)
    return () => {
      console.log('Компонент размонтируется или userId изменился');
    };
  }, [userId]); // Массив зависимостей: эффект сработает при изменении userId

  if (loading) return <div>Загрузка...</div>;

  return (
    <div>
      <h2>{user.name}</h2>
      <p>{user.email}</p>
    </div>
  );
}

3. useContext — работа с контекстом

useContext позволяет подписаться на контекст без использования Consumer. Это упрощает доступ к глобальным данным (например, теме, языку, состоянию авторизации).

import React, { useContext, createContext } from 'react';

const ThemeContext = createContext('light');

function ThemedButton() {
  const theme = useContext(ThemeContext); // Получаем текущую тему

  return (
    <button style={{
      background: theme === 'dark' ? '#333' : '#FFF',
      color: theme === 'dark' ? '#FFF' : '#333'
    }}>
      Тема: {theme}
    </button>
  );
}

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <ThemedButton />
    </ThemeContext.Provider>
  );
}

4. useReducer — альтернатива useState для сложного состояния

useReducer предпочтителен, когда следующее состояние зависит от предыдущего, или логика обновления сложная. Похож на Redux.

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 };
    case 'reset':
      return initialState;
    default:
      throw new Error('Неизвестное действие');
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <p>Счет: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>
        Увеличить
      </button>
      <button onClick={() => dispatch({ type: 'decrement' })}>
        Уменьшить
      </button>
      <button onClick={() => dispatch({ type: 'reset' })}>
        Сбросить
      </button>
    </div>
  );
}

5. Кастомные хуки — повторное использование логики

Кастомные хуки позволяют инкапсулировать и переиспользовать логику между компонентами. Это функции, имя которых начинается с use, и которые могут вызывать другие хуки.

import { useState, useEffect } from 'react';

// Кастомный хук для отслеживания ширины окна
function useWindowWidth() {
  const [width, setWidth] = useState(window.innerWidth);

  useEffect(() => {
    const handleResize = () => setWidth(window.innerWidth);
    window.addEventListener('resize', handleResize);
    
    // Очистка при размонтировании
    return () => window.removeEventListener('resize', handleResize);
  }, []); // Пустой массив зависимостей = эффект только при монтировании

  return width;
}

function ResponsiveComponent() {
  const width = useWindowWidth(); // Используем кастомный хук

  return (
    <div>
      <p>Ширина окна: {width}px</p>
      {width < 768 ? <p>Мобильный вид</p> : <p>Десктопный вид</p>}
    </div>
  );
}

6. useRef — доступ к DOM и хранение мутируемых значений

useRef возвращает мутируемый ref-объект, который сохраняет свое значение между рендерами. Часто используется для доступа к DOM-элементам или хранения значений, не требующих перерисовки.

import React, { useRef, useEffect } from 'react';

function FocusInput() {
  const inputRef = useRef(null);

  useEffect(() => {
    inputRef.current.focus(); // Устанавливаем фокус на инпут при монтировании
  }, []);

  return <input ref={inputRef} type="text" />;
}

7. useMemo и useCallback — оптимизация производительности

  • useMemo мемоизирует вычисления, чтобы избежать дорогостоящих пересчетов при каждом рендере.
  • useCallback мемоизирует функции, предотвращая их пересоздание.
import React, { useState, useMemo, useCallback } from 'react';

function ExpensiveComponent({ list, multiplier }) {
  // Вычисление выполняется только при изменении list или multiplier
  const computedValue = useMemo(() => {
    console.log('Выполняется дорогое вычисление...');
    return list.reduce((sum, item) => sum + item, 0) * multiplier;
  }, [list, multiplier]);

  const handleClick = useCallback(() => {
    console.log('Клик! Значение:', computedValue);
  }, [computedValue]); // Функция не пересоздается при каждом рендере

  return (
    <div>
      <p>Результат: {computedValue}</p>
      <button onClick={handleClick}>Логгировать</button>
    </div>
  );
}

Заключение

Хуки кардинально изменили подход к разработке на React, сделав функциональные компоненты полноценными. Они обеспечивают:

  • Улучшенную композицию логики (кастомные хуки)
  • Избавление от проблем классов (this, привязка методов)
  • Более понятный и тестируемый код

Главное правило: хуки можно вызывать только на верхнем уровне компонентов или других хуков, а не внутри циклов, условий или вложенных функций. Это гарантирует сохранение порядка вызовов хуков между рендерами.

Приведи примеры использования хуков | PrepBro