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

Что такое Hook?

1.2 Junior🔥 241 комментариев
#React

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

🐱
claude-haiku-4.5PrepBro AI21 мар. 2026 г.(ред.)

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

Что такое Hook

Hook это специальная функция в React, которая позволяет «подцепиться» (hook into) к различным функциям React. Они были введены в React 16.8 и полностью изменили способ написания React компонентов, сделав функциональные компоненты столь же мощными, как компоненты-классы.

История: Компоненты-классы vs Функциональные компоненты

Компоненты-классы (до Hooks)

class Counter extends React.Component {
  constructor(props) {
    super(props);
    this.state = { count: 0 };
  }

  componentDidMount() {
    // Когда компонент монтируется
    document.title = this.state.count;
  }

  componentDidUpdate() {
    // Когда компонент обновляется
    document.title = this.state.count;
  }

  componentWillUnmount() {
    // Когда компонент удаляется
    document.title = 'Reset';
  }

  render() {
    return (
      <div>
        <p>Count: {this.state.count}</p>
        <button onClick={() => this.setState({ count: this.state.count + 1 })}>
          Increment
        </button>
      </div>
    );
  }
}

Проблемы:

  • Логика разбросана по разным методам (componentDidMount, componentDidUpdate)
  • Сложно переиспользовать логику между компонентами
  • Много boilerplate кода
  • Сложно для новичков

Функциональные компоненты (с Hooks)

function Counter() {
  const [count, setCount] = React.useState(0);

  React.useEffect(() => {
    document.title = count;

    return () => {
      document.title = 'Reset';
    };
  }, [count]);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </div>
  );
}

Преимущества:

  • Вся логика в одном месте
  • Легко переиспользовать (кастомные хуки)
  • Меньше кода
  • Понятнее для новичков

Что такое Hook - определение

Hook это функция, которая позволяет:

  1. "Подцепиться" к функциям React (состояние, побочные эффекты, контекст и т.д.)
  2. Работать только в функциональных компонентах (или других хуках)
  3. Переиспользовать логику через кастомные хуки

Встроенные Hooks

Hooks для состояния

// 1. useState - управление состоянием
import { useState } from 'react';

function Form() {
  const [name, setName] = useState(''); // Начальное значение ''
  const [email, setEmail] = useState('');
  const [age, setAge] = useState(null);

  return (
    <form>
      <input
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="Name"
      />
      <input
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Email"
      />
    </form>
  );
}

// 2. useReducer - сложное состояние
import { useReducer } from 'react';

function TodoApp() {
  const [todos, dispatch] = useReducer(todosReducer, []);

  return (
    <button onClick={() => dispatch({ type: 'ADD', payload: 'New todo' })}>
      Add
    </button>
  );
}

function todosReducer(state, action) {
  if (action.type === 'ADD') {
    return [...state, action.payload];
  }
  return state;
}

Hooks для побочных эффектов

// 1. useEffect - выполнить код после рендера
import { useEffect } from 'react';

function DataFetcher() {
  const [data, setData] = useState(null);

  useEffect(() => {
    fetch('/api/data')
      .then(res => res.json())
      .then(data => setData(data));
  }, []); // Пустой массив - выполнить один раз

  return <div>{data && JSON.stringify(data)}</div>;
}

// 2. useLayoutEffect - выполнить ПЕРЕД рендером браузером
import { useLayoutEffect } from 'react';

function MeasureElement() {
  const [height, setHeight] = useState(0);
  const ref = useRef(null);

  useLayoutEffect(() => {
    setHeight(ref.current.clientHeight); // Измерить размер
  }, []);

  return <div ref={ref}>Height: {height}</div>;
}

Hooks для оптимизации

// 1. useCallback - мемоизация функции
import { useCallback } from 'react';

function Parent() {
  const [count, setCount] = useState(0);

  const handleClick = useCallback(() => {
    console.log(count);
  }, [count]); // Пересоздать, если count изменился

  return <Child onClick={handleClick} />;
}

// 2. useMemo - мемоизация значения
import { useMemo } from 'react';

function ExpensiveComponent({ data }) {
  const sortedData = useMemo(() => {
    return data.sort((a, b) => a.name.localeCompare(b.name));
  }, [data]); // Пересчитать, если data изменилась

  return <ul>{sortedData.map(item => <li key={item.id}>{item.name}</li>)}</ul>;
}

Hooks для доступа

// 1. useRef - доступ к DOM или mutable значению
import { useRef } from 'react';

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

  const focusInput = () => {
    inputRef.current.focus();
  };

  return (
    <>
      <input ref={inputRef} />
      <button onClick={focusInput}>Focus</button>
    </>
  );
}

// 2. useContext - получить значение контекста
import { useContext, createContext } from 'react';

const ThemeContext = createContext();

function ThemedButton() {
  const { theme } = useContext(ThemeContext);
  return <button style={{ background: theme === 'dark' ? '#000' : '#fff' }}>Click</button>;
}

Кастомные Hooks - переиспользование логики

Можно создавать собственные хуки для переиспользования логики:

// Кастомный хук для формы
function useForm(initialValues) {
  const [values, setValues] = useState(initialValues);

  const handleChange = (e) => {
    const { name, value } = e.target;
    setValues(prev => ({ ...prev, [name]: value }));
  };

  const reset = () => setValues(initialValues);

  return { values, handleChange, reset };
}

// Использование в разных компонентах
function LoginForm() {
  const { values, handleChange, reset } = useForm({
    email: '',
    password: ''
  });

  return (
    <form onSubmit={() => { /* submit */ reset(); }}>
      <input name="email" value={values.email} onChange={handleChange} />
      <input name="password" value={values.password} onChange={handleChange} />
    </form>
  );
}

function SignupForm() {
  const { values, handleChange, reset } = useForm({
    name: '',
    email: '',
    password: ''
  });

  return (
    <form onSubmit={() => { /* submit */ reset(); }}>
      <input name="name" value={values.name} onChange={handleChange} />
      <input name="email" value={values.email} onChange={handleChange} />
      <input name="password" value={values.password} onChange={handleChange} />
    </form>
  );
}

Другой пример: Fetch Hook

// Кастомный хук для загрузки данных
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch(url)
      .then(res => res.json())
      .then(data => {
        setData(data);
        setLoading(false);
      })
      .catch(err => {
        setError(err);
        setLoading(false);
      });
  }, [url]);

  return { data, loading, error };
}

// Использование
function UserProfile({ userId }) {
  const { data: user, loading, error } = useFetch(`/api/users/${userId}`);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;

  return <div>{user.name}</div>;
}

Правила использования Hooks

// ❌ НЕПРАВИЛЬНО - вызов в условии
function Component() {
  if (condition) {
    useState(); // ERROR!
  }
}

// ✅ ПРАВИЛЬНО
function Component() {
  const [state, setState] = useState();
  if (condition) {
    // Использовать state здесь
  }
}

// ❌ НЕПРАВИЛЬНО - вызов в цикле
for (let i = 0; i < 10; i++) {
  useState(); // ERROR!
}

// ✅ ПРАВИЛЬНО
const states = [];
for (let i = 0; i < 10; i++) {
  states.push(useState()); // Создать в компоненте один раз
}

// ❌ НЕПРАВИЛЬНО - вызов вне компонента
function outsideComponent() {
  useState(); // ERROR!
}

// ✅ ПРАВИЛЬНО - только в компонентах или других хуках
function Component() {
  useState(); // OK
}

function useCustom() {
  useState(); // OK
}

Зачем нужны Hooks

  1. Переиспользование логики - через кастомные хуки
  2. Разделение по логике - не по жизненному циклу
  3. Простота - меньше кода и boilerplate
  4. Понятность - логика в одном месте
  5. Тестируемость - хуки легче тестировать чем классы

Итого

Hook это:

  • Функция, которая позволяет использовать React функции в функциональных компонентах
  • Способ перейти от классов к функциям
  • Механизм для переиспользования логики (кастомные хуки)
  • Правильный способ управления состоянием в modern React
  • Обязательна база знаний для любого React разработчика
Что такое Hook? | PrepBro