#javascript #reactjs #typescript #next.js
#javascript #reactjs #typescript #next.js
Вопрос:
Главный вопрос заключается в том, как выполнить debounce
функцию с фактическим значением переменной вместо значения, которое было фактическим 500 мс назад?
Во время выполнения debounce
функция, похоже, имеет устаревшие значения аргументов из-за закрытия.
В моем коде я пытаюсь скрыть выпадающий список, только если пользователь выводит мышь из выпадающего списка минимум на 1 секунду. Поэтому, если пользователь покидает мышь из выпадающего списка, а затем сразу же вводит мышь обратно — выпадающий список все равно будет виден.
Но debounceHide
функция никогда не устанавливает active dropdown в null
значение, потому что она использует stillHoverOnDropdown
значение, которое было фактическим 1000 мс назад (поэтому его значение равно true
)
Я помещаю код ниже, но обратите внимание, что это просто для лучшего понимания. Мой код в реальном проекте намного больше, и в нем много ссылок с выпадающими списками.
Также вы увидите onHoverStart
и onHoverEnd
— это равно onMouseEnter
и onMouseLeave
. Пример:
function debounce(fn, ms, ...args) {
let timer;
return () => {
clearTimeout(timer);
timer = setTimeout(() => {
timer = null;
fn.apply(this, args);
}, ms);
};
}
const Navbar = () => {
const [activeDropdown, setActiveDropdown] = useState(null);
const [stillHoverOnDropdown, setStillHoverOnDropdown] = useState(false);
const debounceHide = debounce(
() => {
if (!stillOnDropdown) {
setActiveDropdown(null);
}
},
1000
);
const handleHoverStart = () => {
setStillOnDropdown(true)
}
const handleHoverEnd = () => {
setStillOnDropdown(false)
debounceHide();
}
return (
<>
<motion.a onHoverStart={() => handleDropdownHover(el.id)}>Link</motion.a>
<motion.div onHoverStart={handleHoverStart} onHoverEnd={handleHoverEnd}>Dropdown Content</motion.div>
</>
)
}
Ответ №1:
Я нашел ответ на свой вопрос. Когда setTimeout
запланировано, оно использует значение stillOnDropdown
в то время, когда оно было запланировано.
useRef
может решить эту проблему.
// Use a ref to access the current count value in
// an async callback.
const countRef = useRef(count);
countRef.current = count;
const getCountTimeout = () => {
setTimeout(() => {
setTimeoutCount(countRef.current);
}, 2000);
};