быстрая сводка
Я пытаюсь создать кнопку, которая имеет как обычный щелчок, так и отдельное действие, которое происходит, когда пользователь нажимает и удерживает ее, аналогично кнопке «Назад» в Chrome.
То, как я это делаю, включает setTimeout()
с обратным вызовом, который проверяет что-то в состоянии.По какой-то причине обратный вызов использует состояние с момента вызова setTimeout()
, а не с момента его вызова (1 секунда спустя).
Вы можете просмотреть его на codesandbox
, как я пытаюсь сделать это
Чтобы получить эту функцию, я звоню setTimeOut()
onMouseDown.Я также установил isHolding, который находится в состоянии, в true.
onMouseUp Я устанавливаю isHolding в false и также запускаю clickHandler()
, что является опорой, если функция удержания не успела быть вызвана.
Обратный вызов в setTimeOut()
будетпроверьте, является ли isHolding истиной, и если это так, он запустит clickHoldHandler()
, что является опорой.
problem
isHolding находится в состоянии (я использую хуки), но когдаsetTimeout()
запускает обратный вызов, я не возвращаю текущее состояние, но какое состояние было при первом вызове setTimetout()
.
мой код
Вот как я делаюэто:
const Button = ({ clickHandler, clickHoldHandler, children }) => {
const [isHolding, setIsHolding] = useState(false);
const [holdStartTime, setHoldStartTime] = useState(undefined);
const holdTime = 1000;
const clickHoldAction = e => {
console.log(`is holding: ${isHolding}`);
if (isHolding) {
clickHoldHandler(e);
}
};
const onMouseDown = e => {
setIsHolding(true);
setHoldStartTime(new Date().getTime());
setTimeout(() => {
clickHoldAction(e);
}, holdTime);
};
const onMouseUp = e => {
setIsHolding(false);
const totalHoldTime = new Date().getTime() - holdStartTime;
if (totalHoldTime < holdTime || !clickHoldHandler) {
clickHandler(e);
}
};
const cancelHold = () => {
setIsHolding(false);
};
return (
<button
onMouseDown={onMouseDown}
onMouseUp={onMouseUp}
onMouseLeave={cancelHold}
>
{children}
</button>
);
};