useCallback с [] сохраняет первый btnClick, который замкнул count=0, поэтому каждый клик задаёт 1. Второй обработчик отдельно мутирует объект state и передаёт прежнюю ссылку.
Поиск причины неправильного инкремента счётчика в React‑компоненте
useCallback с [] сохраняет первый btnClick, который замкнул count=0, поэтому каждый клик задаёт 1. Второй обработчик отдельно мутирует объект state и передаёт прежнюю ссылку.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
При каждом нажатии на первую кнопку ожидается, что значение будет возрастать на 1, отражая общее количество кликов. В текущей реализации счётчик увеличивается лишь один раз. Необходимо проанализировать код, выяснить, почему состояние не меняется при каждом событии, и предложить исправление.
import { useCallback, useEffect, useMemo, useState } from "react";
export function App() {
const [count, setCount] = useState(0);
const [count2, setCount2] = useState({
name: 'Anton',
});
const handleBtnClick2 = () => {
count2.name = "Alex";
console.log(count2.name);
setCount2(count2);
};
const btnClick = () => {
setCount(count + 1);
};
const handleBtnClick = useCallback(() => {
btnClick();
}, []);
return (
<div>
<button onClick={handleBtnClick}>{count}</button>
<button onClick={handleBtnClick2}>{count2.name}</button>
{/* <button onClick={btnClick2}>Compute Heavy</button> */}
<div />
<input type="text" />
</div>
);
}
Ответ
useCallback с [] сохраняет первый btnClick, который замкнул count=0, поэтому каждый клик задаёт 1. Второй обработчик отдельно мутирует объект state и передаёт прежнюю ссылку.
const handleBtnClick = useCallback(() => {
setCount(value => value + 1);
}, []);
const handleBtnClick2 = () => {
setCount2(previous => ({ ...previous, name: 'Alex' }));
};
Функциональный updater получает актуальное значение без зависимости от count. Для объекта создаётся новая ссылка, чтобы React увидел обновление; прямую запись count2.name нужно убрать. Если мемоизация первой кнопке не нужна, useCallback можно вообще не использовать и оставить обычный обработчик с функциональным обновлением.