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

Что будет если передать useState в функцию?

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

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

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

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

Вопрос о передаче useState в функцию

Если коротко, то передать в функцию можно, но это почти всегда бессмысленно и приведёт к ошибкам или нерабочему коду. Давайте разберём этот вопрос подробно, так как он затрагивает фундаментальные принципы работы React Hooks.

Что такое useState и что он возвращает?

Хук useState возвращает массив из двух элементов:

  1. Текущее значение состояния
  2. Функцию-сеттер для обновления этого состояния
const [count, setCount] = useState(0);
// Возвращает: [0, function setCount(newValue) {...}]

В этом примере count — это примитивное число, а setCount — функция. Передать саму функцию useState куда-либо нельзя, так как это импорт из React (import { useState } from 'react'), это готовая функция из библиотеки.

Вопрос, скорее всего, подразумевает: "Что будет, если передать результат вызова useState (то есть массив [state, setState]) или его части в другую функцию?". Рассмотрим оба варианта.


1. Передача значения состояния в функцию

Это обычная и частая практика. Значение состояния — это просто данные (число, строка, объект, массив).

const [user, setUser] = useState({ name: 'Alex' });

// Передаём значение состояния во внешнюю функцию
const processUserData = (userData) => {
  return userData.name.toUpperCase();
};

const userNameUpper = processUserData(user); // Работает корректно

Здесь нет проблем. Значение состояния — это "снимок" (snapshot) на момент рендера. Вы передаёте просто данные. Даже если внутри processUserData данные изменятся, это не повлияет на состояние в React. React-состояние обновляется только через сеттер (setUser).


2. Передача функции-сеттера в другую функцию

Это также распространённый и правильный паттерн, особенно для колбэков или при подъёме состояния (lifting state up).

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

// Функция, которая принимает сеттер как аргумент
const incrementCounter = (setterFunction) => {
  setterFunction(prev => prev + 1); // Используем функциональную форму
};

// Передаём сеттер во внешнюю функцию
<button onClick={() => incrementCounter(setCount)}>+1</button>

Это работает корректно. Сеттер — это стабильная функция (её ссылка не меняется между рендерами), которую можно передавать куда угодно. Она "знает", как обновить конкретное состояние в конкретном компоненте, даже если вызвана извне.


3. Передача всего массива [state, setState] в функцию

Технически возможно, но крайне не рекомендуется и является антипаттерном. Вы передаёте "пакет" состояния.

const useCounter = () => {
  const [count, setCount] = useState(0);
  return [count, setCount];
};

const MyComponent = () => {
  const counterArray = useCounter();

  // Передаём весь массив в функцию
  const handleClick = ([currentCount, setter]) => {
    setter(currentCount + 1);
  };

  return <button onClick={() => handleClick(counterArray)}>Click</button>;
};

Почему это плохо:

  • Нарушение инкапсуляции. Функция handleClick получает избыточные данные. Ей, возможно, нужен только сеттер, но она вынуждена деструктурировать массив.
  • Сложность тестирования. Функция теперь зависит от структуры массива, возвращаемого useState.
  • Путаница в коде. Паттерн "возвращать массив" используется в кастомных хуках для гибкости, но внутри компонента логичнее работать с именованными переменными через деструктуризацию сразу.

Ключевой нюанс: Правила Hooks

Если вы решите передать сеттер или состояние в функцию, вы должны помнить о правилах Hooks:

// ❌ НЕПРАВИЛЬНО — вызов хука внутри обычной функции
const dangerousFunction = (setter) => {
  useEffect(() => { // Хук вызван НЕ внутри компонента или кастомного хука!
    console.log('Это вызовет ошибку!');
  }, []);
  setter(10);
};

// ✅ ПРАВИЛЬНО — обычная функция, которая НЕ вызывает хуки
const safeFunction = (setter, value) => {
  // Здесь можно вызывать только сеттер, но не другие хуки
  setter(value);
};

Функция-сеттер — это НЕ хук, её можно вызывать где угодно. А вот useState, useEffect и другие хуки можно вызывать только на верхнем уровне функционального компонента или кастомного хука.


Итог и практические рекомендации

  1. Значение состояния — это данные. Передавать их в функции безопасно.
  2. Функцию-сеттер — можно и нужно передавать для обновления состояния из колбэков, дочерних компонентов или утилитных функций.
  3. Целиком массив [state, setState] — передавать не рекомендуется из-за ухудшения читаемости.
  4. Саму функцию useState (импорт из React) — передавать бессмысленно, так как хук должен вызываться непосредственно в компоненте для создания конкретного состояния.

Правильный паттерн — создавать чистые (pure) функции-хэндлеры, которые принимают сеттер или данные:

// Чистая функция, которую легко тестировать
export const calculateNewCount = (current, delta) => current + delta;

const MyComponent = () => {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    // Передаём значение состояния и получаем новое
    const newCount = calculateNewCount(count, 5);
    // Передаём сеттер в условную функцию-логику
    updateStateSafely(setCount, newCount);
  };

  return <button onClick={handleClick}>+5</button>;
};

// Утилитная функция, работающая с любым сходным сеттером
function updateStateSafely(setter, value) {
  if (value > 100) {
    setter(100); // Добавляем бизнес-логику
  } else {
    setter(value);
  }
}

Таким образом, передача частей результата useState — это нормальная практика, которая лежит в основе композиции и повторного использования кода в React. Главное — чётко разделять, что является данными, что является функцией обновления, и не нарушать правила вызова хуков.