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

Что Hooks внесли в React?

1.6 Junior🔥 251 комментариев
#React

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

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

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

Что Hooks внесли в React

Появление Hooks в React 16.8 (февраль 2019) было революционным изменением, которое полностью трансформировало экосистему React. Это не просто синтаксический сахар - это переосмысление того, как мы пишем React компоненты.

До Hooks: Эра компонентов-классов

Проблемы, которые были

// Логика разбросана по жизненным циклам
class UserProfile extends React.Component {
  componentDidMount() {
    // Подписаться на изменения пользователя
    this.unsubscribe = store.subscribe(this.updateUser);
    // Загрузить дополнительные данные
    this.fetchData();
    // Настроить таймер
    this.timer = setInterval(() => {
      this.checkUpdates();
    }, 5000);
  }

  componentDidUpdate(prevProps) {
    // Повторить логику, если user изменился
    if (prevProps.userId !== this.props.userId) {
      this.fetchData();
    }
  }

  componentWillUnmount() {
    // Очистить ВСЕ, что создавали выше (сложно не забыть)
    this.unsubscribe();
    clearInterval(this.timer);
  }

  render() {
    return <div>{this.state.user.name}</div>;
  }
}

Проблемы:

  1. Связанная логика разбросана по разным методам
  2. Сложно найти все place, где обновляется состояние
  3. Легко забыть cleanup в componentWillUnmount
  4. Трудно переиспользовать логику между компонентами
  5. Много boilerplate кода (constructor, super, this binding)

После Hooks: Логика по функциональности

function UserProfile({ userId }) {
  // Управление пользователем
  const [user, setUser] = useState(null);
  useEffect(() => {
    const unsubscribe = store.subscribe(() => {
      setUser(store.getState().user);
    });
    return () => unsubscribe(); // Cleanup
  }, []);

  // Загрузка данных
  useEffect(() => {
    fetchUserData(userId).then(setUser);
  }, [userId]); // Автоматически переупорядочивается если userId изменился

  // Таймер
  useEffect(() => {
    const timer = setInterval(() => {
      checkUpdates();
    }, 5000);
    return () => clearInterval(timer); // Cleanup
  }, []);

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

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

  1. Каждый useEffect - отдельная логика
  2. Cleanup находится рядом с логикой
  3. Автоматическое переупорядочивание благодаря зависимостям
  4. Меньше кода

Что именно Hooks изменили

1. Переиспользование логики (Custom Hooks)

Раньше (Render Props, Higher Order Components):

// Очень сложно и громоздко
function withTheme(Component) {
  return (props) => (
    <ThemeContext.Consumer>
      {theme => <Component {...props} theme={theme} />
    </ThemeContext.Consumer>
  );
}

const ThemedButton = withTheme(Button);

// Если нужны несколько HOC - наступает HOC Hell
const Component = withAuth(withTheme(withData(MyComponent)));

Сейчас (Custom Hooks):

// Просто функция, которую можно переиспользовать
function useTheme() {
  return useContext(ThemeContext);
}

function useAuth() {
  const [user, setUser] = useState(null);
  // логика аутентификации
  return { user, login, logout };
}

// Использование - просто вызвать хуки
function MyComponent() {
  const theme = useTheme();
  const { user, login } = useAuth();
  // ...
}

2. Управление состоянием (State Management)

Раньше:

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

  increment = () => {
    this.setState({ count: this.state.count + 1 });
  };

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

Сейчас:

function Counter() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      Count: {count}
      <button onClick={() => setCount(count + 1)}>+</button>
    </div>
  );
}

// Или с useReducer для сложного состояния
function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  // ...
}

3. Функциональные компоненты стали мощнее классов

Раньше:

  • Функциональные компоненты были ограничены (только props)
  • Нужны были классы для состояния и побочных эффектов

Сейчас:

  • Функциональные компоненты имеют все возможности классов
  • Плюс дополнительные преимущества (легче тестировать, менее verbose)

4. Производительность

// useCallback - мемоизация функций
const handleClick = useCallback(() => {
  // функция не пересоздается, если deps не изменились
}, [deps]);

// useMemo - мемоизация вычислений
const expensiveValue = useMemo(() => {
  return computeExpensive(data);
}, [data]);

// Раньше нужны были сложные оптимизации
// shouldComponentUpdate, PureComponent

5. Тестирование

Раньше - сложно:

// Нужно:  mount компонент, вызывать методы, проверять this.state
import { mount } from 'enzyme';

const wrapper = mount(<Counter />);
wrapper.find('button').simulate('click');
expect(wrapper.find('.count').text()).toBe('1');

Сейчас - просто:

// Тестируем хук отдельно
import { renderHook, act } from '@testing-library/react';
import { useCounter } from './useCounter';

const { result } = renderHook(() => useCounter());
act(() => {
  result.current.increment();
});
expect(result.current.count).toBe(1);

Экосистемные изменения

1. Появились новые library patterns

// До: всё базировалось на HOC и Render Props
// Сейчас: простые hook-based библиотеки

// react-query (данные)
const { data, isLoading } = useQuery('users', fetchUsers);

// zustand (состояние)
const count = useStore((state) => state.count);

// react-hook-form (формы)
const { register, handleSubmit } = useForm();

2. Меньше нужно знать для начинающих

// Раньше нужно было понимать:
// - this binding
// - жизненные циклы
// - классы в JavaScript
// - разница между constructor и componentDidMount

// Сейчас начинающий может писать:
function MyComponent() {
  const [count, setCount] = useState(0);
  
  useEffect(() => {
    // побочные эффекты
  }, [count]);
  
  return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}
// Готово! Не нужно знать про классы.

3. Миграция экосистемы

// Большинство популярных библиотек переработали API на hooks:
// - React Router (useParams, useHistory, useLocation)
// - Redux (useDispatch, useSelector)
// - GraphQL (useQuery, useMutation)
// - Axios/Fetch (useQuery, useFetch)

// Старый способ (React Router v5):
const params = this.props.match.params;
const history = this.props.history;

// Новый (React Router v6):
const params = useParams();
const navigate = useNavigate();

Глубокие изменения

1. Способ думать о компонентах

Раньше: Компонент = класс с жизненными циклами

class User extends React.Component {
  componentDidMount() { }
  componentDidUpdate() { }
  componentWillUnmount() { }
  render() { }
}

Сейчас: Компонент = функция, которая возвращает UI

function User() {
  // состояние
  // побочные эффекты
  // логика
  return UI;
}

2. Направление данных

Раньше: Props вниз, callbacks вверх (сложно)

// Нужно проходить через все компоненты
<App>
  <Parent onUpdate={handleUpdate}>
    <Child onUpdate={onUpdate} />
  </Parent>
</App>

Сейчас: Context API + Hooks (просто)

const UserContext = createContext();

function App() {
  const [user, setUser] = useState();
  
  return (
    <UserContext.Provider value={{ user, setUser }}>
      <AnyComponent /> {/* может доступ к user отсюда */}
    </UserContext.Provider>
  );
}

function AnyComponent() {
  const { user, setUser } = useContext(UserContext);
}

Статистика

  • В 2024 году 95%+ новых React проектов используют только функциональные компоненты с hooks
  • Классы считаются "legacy" паттерном
  • Большинство tutorials и документации сфокусированы на hooks

Итого

Hooks внесли:

  1. Логика по функциональности - связанная логика в одном месте
  2. Переиспользование - простые кастомные хуки вместо HOC
  3. Доступность - проще для новичков
  4. Производительность - встроенная мемоизация
  5. Тестируемость - проще тестировать
  6. Экосистема - все библиотеки переделали API
  7. Будущее React - React Suspense, Concurrent Rendering основаны на Hooks

Это был переломный момент в истории React. Сейчас сложно представить React без Hooks.

Что Hooks внесли в React? | PrepBro