Таким образом, ваша анонимная функция заблокирована на начальном значении scrolling
. Это то, как замыкания работают в JS, и вам лучше узнать какую-нибудь симпатичную статью об этом, это может быть сложно, и хуки сильно полагаются на замыкания.
Пока есть 3 различных Решения здесь:
1. Пересоздайте и перерегистрируйте обработчик для каждого изменения
useEffect(() => {
const scrollHandler = () => {
if (scrolling === false) setScrolling(true);
};
window.addEventListener("scroll", scrollHandler);
return () => window.removeEventListener("scroll", scrollHandler);
}, [scrolling]);
, следуя этому пути, убедитесь, что вы возвращаете функцию очистки из useEffect
. Это хороший подход по умолчанию, но для его прокрутки может повлиять на производительность, поскольку событие прокрутки часто вызывает слишком .
2. Доступ к данным по ссылке
const scrolling = useRef(false);
useEffect(() => {
const handler = () => {
if (scrolling.current === false) scrolling.current = true;
};
window.addEventListener("scroll", handler);
return () => window.removeEventListener("scroll", handler);
}, []);
return (
<>
scrolling: {scrolling}
</>
);
недостаток: изменение ссылки не вызывает повторного рендеринга. Поэтому вам нужно иметь какую-то другую переменную, чтобы изменить ее, вызывая повторную визуализацию.
3. Используйте функциональную версию сеттера для доступа к самому последнему значению
(я вижу это как предпочтительный способ здесь):
useEffect(() => {
const scrollHandler = () => {
setScrolling((currentScrolling) => {
if (!currentScrolling) return true;
return false;
});
};
window.addEventListener("scroll", scrollHandler);
return () => window.removeEventListener("scroll", scrollHandler);
}, []);
Примечание Кстати, даже для эффекта одноразового использования, вам лучше вернуть функцию очистки в любом случае .
PS Также сейчас вы не устанавливаете scrolling
в false
, так что вы можете просто избавиться от условия if(scrolling === false)
, но в сценарии реального мира вы можете и столкнуться с чем-то похожим.