Я столкнулся с проблемой при использовании компонентов React и React Material-UI. Что мне нужно:
1) Пользователь нажимает кнопку в моем компоненте - я должен добавить слушателя mousemove на страницу и показать ProgressBar.
2) Пользователь перемещает мышь - я считаю события и обновляю свой ProgressBar.
3) Когда количество событий равно 50, я удаляю слушателя перемещения мыши и скрываю ProgressBar.
Я пытался сделать это с помощью React useEffect, использовать State Hooks, но он не удаляет слушателя. Я не понимаю, почему.
Вот мой код:
const [completed, setCompleted] = React.useState(0);
const [keyGenState, setKeyGenState] = React.useState(0);
const updateMousePosition = ev => {
console.log("UMP");
setCompleted(old => old + 1);
/*I tried to check completed value here, but it always is 0 - maybe, React re-renders component on setState..
And I decided to take useEffect hook (see below)*/
};
useEffect(() => {
console.log(completed); /*Just to understand, what happens) */
if (completed === 49) {
return () => {
/*When completed value is 50, this log message appears, but mouse listener still works! */
console.log("Finish!");
document.removeEventListener("mousemove", updateMousePosition);
setKeyGenState(2);
}
}
}, [completed]);
function handleChange(e) {
switch (e.currentTarget.id) {
/*startKeyGen - it is ID of my Button. When user clicks it, I show ProgressBar and add mousemove listener*/
case "startKeyGen" : {
setKeyGenState(1);
document.addEventListener("mousemove", updateMousePosition);
break;}
}
}
/*Other logics. And finally, JSX code for my ProgressBar from Material-UI*/
<LinearProgress hidden={keyGenState !== 1 } variant="determinate" value={completed} style={{marginTop: 10}} />
Это выглядит очень странно: почему React игнорирует removeEventListener.
Пожалуйста, объясните, где моя ошибка.
UPD: Спасибо большое! Я использовал ловушку useCallback следующим образом:
const updateMousePosition = React.useCallback(
(ev) => {
//console.log("Calback");
console.log(ev.clientX);
setCompleted(old => old + 1);
},
[],
);
useEffect(() => {
//console.log(completed); /*Just to understand, what happens) */
if (completed === 49) {
return () => {
/*When completed value is 50, this log message appears, but mouse listener still works! */
console.log("Finish!");
document.removeEventListener("mousemove", updateMousePosition);
setKeyGenState(2);
}
}
});
Но я все еще не до конца понимаю. Поэтому, когда я использовал useCallback с пустым массивом зависимостей, эта функция (updateMousePosition) , останется неизменным в течение всей «жизни» моего компонента?
А в использовании Effect я удаляю mouseListener. Для меня это волшебный c: почему useEffect игнорирует удаление без использования Callback?