#reactjs #settimeout #cleartimeout #usecallback
Вопрос:
https://codepen.io/evan-jin/pen/qBjGWvR
const [hoverItem, setHoverItem] = useState(null)
const timerRef = useRef(null)
const addcursor = useCallback(() => {
console.log('addcursor')
clearTimeout(timerRef.current)
timerRef.current = null
timerRef.current = setTimeout(() => {
document.body.style.cursor = 'wait'
}, 10)
}, [])
const removeCursor = useCallback(() => {
if (timerRef.current === null) return
console.log('removeCursor')
timerRef.current = setTimeout(() => {
document.body.style.cursor = 'default'
}, 500)
}, [])
useEffect(() => {
if (hoverItem) {
addcursor()
} else {
removeCursor()
}
}, [hoverItem])
Я хочу сохранить «курсор ожидания» при наведении курсора на поле div, но setTimeout срабатывает, когда я перестаю перемещать курсор.
Я пытался использовать clearTimeout при возврате useEffect(willUnmount), но это не работает.
Это работает, если я перемещаюсь внутрь и наружу по каждому компоненту коробки, но если я быстро перемещаю курсор на другой компонент, в конце концов он запускает RemoveCursor setTimeout.
Подводить итоги,
- Я хочу сохранить «ожидание курсора» в течение 500 мс, когда я перемещу курсор
- После прохождения через коробки «курсор ожидания» должен оставаться на коробке, если курсор находится на ней, а не просто исчезать
этот вопрос выглядит странно, но я только что создал эту простую проблему для своего реального проекта, пожалуйста, кто-нибудь, помогите мне..!
Ответ №1:
Наконец-то я нашел проблему! так как я объявил временную ссылку в каждом компоненте элемента. Таким образом, каждый раз, когда он ссылается на таймер каждого элемента. И я мог бы просто решить эту проблему, объявив timerRef в родительском компоненте! Я оставлю код по этой ссылке. спасибо за ваши усилия, ребята.
Ответ №2:
Похоже, вы используете тайм-аут не обязательно. Вы можете достичь того, что пытаетесь сделать, и без setTimeout
этого .
const { useState, useEffect, useCallback, useRef } = React
const Item = ({ num }) => {
const [hoverItem, setHoverItem] = useState(null)
const addCaption = useCallback(() => {
console.log('addCaption')
document.body.style.cursor = 'wait'
}, [])
const removeCaption = useCallback(() => {
console.log('removeCaption')
document.body.style.cursor = 'grab'
}, [])
useEffect(() => {
if (hoverItem) {
addCaption()
} else {
removeCaption()
}
}, [hoverItem])
return (
<div
className='square'
name={num}
id={num}
onMouseEnter={e => setHoverItem(e.target.id)}
onMouseLeave={e => setHoverItem(null)}
/>
)
}
const App = () => {
return (
<div className='wrapper'>
{[...Array(12)].map((_, i) => (
<Item key={i} num={i} />
))}
</div>
)
}
ReactDOM.render( <App/>, document.getElementById("root") )
Комментарии:
1. О, подробностей моего вопроса было недостаточно, и я виноват! на самом деле я хочу сохранить «курсор ожидания» в течение 500 мс, когда я перемещаю курсор
Ответ №3:
Потому что вы представляете состояние для каждого элемента, но вам нужно только одно состояние (обозначающее «курсор находится внутри любого элемента или нет»). Просто переместите свое состояние в родительский компонент, и ваш код будет работать.
const { useState, useEffect, useCallback, useRef } = React;
const Item = ({ num, onMouseEnter, onMouseLeave }) => {
return (
<div
className="square"
name={num}
id={num}
onMouseEnter={onMouseEnter}
onMouseLeave={onMouseLeave}
/>
);
};
const App = () => {
const [hoverItem, setHoverItem] = useState(null);
const timerRef = useRef(null);
const addcursor = useCallback(() => {
console.log("addcursor");
document.body.style.cursor = "wait";
clearTimeout(timerRef.current);
}, []);
const removeCursor = useCallback(() => {
console.log("removecursor");
clearTimeout(timerRef.current);
timerRef.current = setTimeout(() => {
document.body.style.cursor = "default";
}, 500);
}, []);
useEffect(() => {
if (hoverItem) {
addcursor();
} else {
removeCursor();
}
}, [hoverItem]);
return (
<div className="wrapper">
{[...Array(12)].map((_, i) => (
<Item
key={i}
num={i}
onMouseEnter={(e) => setHoverItem(e.target.id)}
onMouseLeave={(e) => setHoverItem(null)}
/>
))}
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));
Комментарии:
1. Я пробовал это раньше, и если вы добавите «консоль». войдите в компонент элемента, 12 элементов будут повторно отображаться каждый раз, когда каждый компонент будет зависать. и, наконец, нашли проблему и оставили решение под вашим ответом! кстати, большое спасибо за ваши усилия!