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

Для чего используется первый аргумент useCallback?

1.0 Junior🔥 12 комментариев
#Другое

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

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

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

Для чего используется первый аргумент useCallback

useCallback — это React хук, но в контексте Node.js Backend интервью этот вопрос может появиться при работе с фронтенд-бэкенд интеграцией или Full Stack знаний.

Примечание: useCallback — это фронтенд концепция (React), не бэкенд. Но объясню для полноты.

Что такое useCallback

useCallback — это React хук для мемоизации функции. Первый аргумент — это сама функция, которую нужно мемоизировать.

// Синтаксис
useCallback(callback, dependencies)

// Первый аргумент — функция
useCallback(() => {
  // код функции
}, [dependencies])

Назначение первого аргумента

Первый аргумент — это функция, которую нужно мемоизировать и переиспользовать между рендерами.

function Counter() {
  const [count, setCount] = useState(0);
  
  // Без useCallback — каждый рендер создаёт новую функцию
  const handleClick = () => {
    setCount(count + 1);
  };
  
  // С useCallback — функция остаётся той же между рендерами
  const handleClickMemo = useCallback(() => {
    setCount(c => c + 1);
  }, []);
  
  return <button onClick={handleClickMemo}>Count: {count}</button>;
}

Проблема без useCallback

function Parent() {
  const [count, setCount] = useState(0);
  
  // Эта функция создаётся заново при каждом рендере
  const handleClick = () => {
    setCount(count + 1);
  };
  
  // Child получает НОВУЮ функцию при каждом рендере
  return <Child onClick={handleClick} />;
}

// Компонент Child
function Child({ onClick }) {
  // Даже если onClick одинаков логически, это разные функции
  // React.memo не поможет, потому что каждый раз новая функция
  return <button onClick={onClick}>Click</button>;
}

Решение с useCallback

function Parent() {
  const [count, setCount] = useState(0);
  
  // useCallback гарантирует, что handleClick остаётся одинаков
  // пока зависимости не изменились
  const handleClick = useCallback(() => {
    setCount(c => c + 1);
  }, []);  // Пустой массив = функция не изменяется никогда
  
  return <Child onClick={handleClick} />;
}

// Теперь Child не будет перерендериваться без причины
const Child = React.memo(({ onClick }) => {
  return <button onClick={onClick}>Click</button>;
});

Зависимости (второй аргумент)

Второй аргумент — это массив зависимостей. Функция пересоздаётся ТОЛЬКО когда одна из зависимостей изменяется.

function Form() {
  const [name, setName] = useState('');
  const [age, setAge] = useState(0);
  
  // Функция зависит от age, пересоздаётся когда age меняется
  const handleSubmit = useCallback(() => {
    console.log(`Name: ${name}, Age: ${age}`);
  }, [age]);  // зависит только от age
  
  return (
    <>
      <input value={name} onChange={(e) => setName(e.target.value)} />
      <input value={age} onChange={(e) => setAge(Number(e.target.value))} />
      <button onClick={handleSubmit}>Submit</button>
    </>
  );
}

Когда использовать useCallback

Используй когда:

  1. Функция передаётся в child компонент с React.memo
  2. Функция используется как зависимость в другом хуке
  3. Оптимизируешь производительность

Не используй когда:

  1. Функция не передаётся в другие компоненты
  2. Нет проблем с производительностью
  3. Усложняешь код без пользы

Сравнение с обычной функцией

function Example() {
  const [count, setCount] = useState(0);
  
  // Без useCallback
  const handleA = () => {
    setCount(count + 1);
  };
  // handleA НОВАЯ функция при каждом рендере
  
  // С useCallback
  const handleB = useCallback(() => {
    setCount(c => c + 1);
  }, []);
  // handleB одинаковая между рендерами (пока deps не изменились)
  
  // Проверка
  console.log(handleA === handleA);  // false (новая функция)
  console.log(handleB === handleB);  // true (одна и та же)
}

Идентичность функции (Function Identity)

// В JavaScript функции сравниваются по идентичности
const fn1 = () => {};
const fn2 = () => {};
console.log(fn1 === fn2);  // false (разные функции)
console.log(fn1 === fn1);  // true (одна и та же)

// useCallback сохраняет идентичность
const memoizedFn = useCallback(() => {}, []);
const memoizedFn2 = useCallback(() => {}, []);
console.log(memoizedFn === memoizedFn2);  // false
console.log(memoizedFn === memoizedFn);   // true (между рендерами)

Практический пример: поиск

function SearchUsers() {
  const [query, setQuery] = useState('');
  
  // Мемоизируем функцию поиска
  const handleSearch = useCallback(async (searchTerm) => {
    const results = await fetch(`/api/search?q=${searchTerm}`);
    return results.json();
  }, []);
  
  return <SearchInput onSearch={handleSearch} />;
}

const SearchInput = React.memo(({ onSearch }) => {
  // Будет вызвана ТОЛЬКО если onSearch изменилась
  useEffect(() => {
    // запрос при изменении функции
  }, [onSearch]);
  
  return <input onChange={(e) => onSearch(e.target.value)} />;
});

Ловушки

1. Забыл добавить зависимость

// Плохо — функция не обновляется при изменении user
const handleSave = useCallback(() => {
  api.save(user.id, data);  // user может быть старый!
}, []);  // Забыл user в зависимостях

// Правильно
const handleSave = useCallback(() => {
  api.save(user.id, data);
}, [user.id]);  // Добавляем зависимость

2. Не нужен useCallback для простых функций

// Не нужен
const handleClick = useCallback(() => {
  setName('John');
}, []);

// Просто используй
const handleClick = () => setName('John');

Для Node.js бэкенда

В Node.js нет useCallback (это React), но концепция мемоизации функций применяется:

// Мемоизированная функция в Node.js
function memoize<T extends (...args: any[]) => any>(fn: T): T {
  const cache = new Map();
  return ((...args: any[]) => {
    const key = JSON.stringify(args);
    if (cache.has(key)) {
      return cache.get(key);
    }
    const result = fn(...args);
    cache.set(key, result);
    return result;
  }) as T;
}

const fibonacci = memoize((n: number): number => {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
});

Вывод: useCallback — это React хук для мемоизации функций. Первый аргумент — это функция, которую нужно мемоизировать. Используй когда функция передаётся в child компоненты или используется как зависимость. Не переусложняй код для незначительной оптимизации.

Для чего используется первый аргумент useCallback? | PrepBro