Причина, по которой alert
показывает устаревшее значение count
, заключается в том, что обратный вызов, переданный в setTimeout
, ссылается на устаревшее значение count
, захваченное закрытием . Обычно это называется устаревшим закрытием .
При первоначальном рендеринге анонимная функция, переданная как обратный вызов setTimeout
, захватывает значение count
как 0
, и когда нажимается кнопка show alert
, обратный вызов ставится в очередь, но с устаревшим значением count.
В приведенном выше случае самое простое решение для отображения обновленного значения count в сообщении с предупреждением и исправления устаревшего -closure проблема заключается в использовании ref
.
function App() {
const [count, setCount] = useState(0);
const latestValue = useRef(count);
const handleAlertClick = () => {
setTimeout(() => {
alert(`count is: ${latestValue.current}`);
}, 3000);
};
return (
<div>
<p>You clicked {count} times</p>
<button
onClick={() => {
setCount(prev => {
latestValue.current = prev + 1;
return prev + 1;
});
}}
>
Click me
</button>
<button onClick={handleAlertClick}>Show alert</button>
</div>
);
}
Рабочая демонстрация в codeandbox
Работа хуков в значительной степени зависит от замыканий, поэтому очень вероятно, что вы можете столкнуться с проблемами, касающимися устаревших закрытий . Вот хорошая статья о том, как устаревшие замыкания создают проблемы при использовании перехватчиков реакции, и демонстрирует, как исправить некоторые проблемы в некоторых ситуациях.