延迟 React onMouseOver 事件
Delay React onMouseOver event
我有一个元素列表,当悬停其中一个时,我想改变我的状态。
<ListElement onMouseOver={() => this.setState({data})}>Data</ListElement>
不幸的是,如果我将鼠标移到列表上,我的状态会快速连续改变几次。我想延迟状态更改,以便它在被解雇之前等待半秒钟。有办法吗?
您可以使用 debounce
作为专用包或从 lodash
获取它,等等:
Useful for implementing behavior that should only happen after a repeated action has completed.
const debounce = require('debounce');
class YourComponent extends Component {
constructor(props) {
super(props);
this.debouncedMouseOver = debounce(handleMouseOver, 200);
}
handleMouseOver = data => this.setState({ data });
render() {
const data = [];
return <ListElement onMouseOver={() => this.debouncedMouseOver(data)}>Data</ListElement>;
}
}
您可以创建一个方法,在满足特殊要求时触发 onMouseOver
事件。
在进一步的例子中,它在500 ms
之后触发。
/**
* Hold the descriptor to the setTimeout
*/
protected timeoutOnMouseOver = false;
/**
* Method which is going to trigger the onMouseOver only once in Xms
*/
protected mouseOverTreatment(data) {
// If they were already a programmed setTimeout
// stop it, and run a new one
if (this.timeoutOnMouseOver) {
clearTimeout(this.timeoutOnMouseOver);
}
this.timeoutOnMouseOver = setTimeout(() => {
this.setState(data);
this.timeoutOnMouseOver = false;
}, 500);
}
结合使用 onMouseEnter
、onMouseLeave
和 setTimeout
.
,您可以通过以下方法将事件延迟 500 毫秒
请记住,数据的状态更新可以由父组件管理并作为 prop 传入。
import React, { useState } from 'react'
const ListElement = () => {
const [data, setData] = useState(null)
const [delayHandler, setDelayHandler] = useState(null)
const handleMouseEnter = event => {
setDelayHandler(setTimeout(() => {
const yourData = // whatever your data is
setData(yourData)
}, 500))
}
const handleMouseLeave = () => {
clearTimeout(delayHandler)
}
return (
<div
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
I have a delayed event handler
</div>
)
}
export default ListElement
debounce
如果您想在一个时间范围内限制操作,那总是答案。
实现简单,无需外部库。
实施:
type Fnc = (...args: any[]) => void;
// default 300ms delay
export function debounce<F extends Fnc>(func: F, delay = 300) {
type Args = F extends (...args: infer P) => void ? P : never;
let timeout: any;
return function (this: any, ...args: Args) {
clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
用法:
...
/** any action you want to debounce */
function foo(
data: any,
event: React.MouseEvent<HTMLDivElement, MouseEvent>
): void {
this.setState({data});
}
const fooDebounced = debounce(foo, 500);
<ListElement onMouseOver={fooDebounced.bind(null, data)}>
Data
</ListElement>
...
您实际上不必 bind
一个函数,但如果您遍历多个元素以避免为每个元素初始化一个新函数,这是一个好习惯。
我可能来晚了一点,但我想使用 Lodash debounce
添加到上面的一些答案中。在对方法进行去抖动时,debounce
函数可让您根据某些事件取消对方法的调用。请参阅功能组件示例:
const [isHovered, setIsHovered] = React.useState(false)
const debouncedHandleMouseEnter = debounce(() => setIsHovered(true), 500)
const handlOnMouseLeave = () => {
setIsHovered(false)
debouncedHandleMouseEnter.cancel()
}
return (
<div
onMouseEnter={debouncedHandleMouseEnter}
onMouseLeave={handlOnMouseLeave}
>
... do something with isHovered state...
</div>
)
此示例仅在用户将鼠标悬停在您的元素中 500 毫秒后才调用您的函数,如果鼠标离开该元素,调用将被取消。
我有一个元素列表,当悬停其中一个时,我想改变我的状态。
<ListElement onMouseOver={() => this.setState({data})}>Data</ListElement>
不幸的是,如果我将鼠标移到列表上,我的状态会快速连续改变几次。我想延迟状态更改,以便它在被解雇之前等待半秒钟。有办法吗?
您可以使用 debounce
作为专用包或从 lodash
获取它,等等:
Useful for implementing behavior that should only happen after a repeated action has completed.
const debounce = require('debounce');
class YourComponent extends Component {
constructor(props) {
super(props);
this.debouncedMouseOver = debounce(handleMouseOver, 200);
}
handleMouseOver = data => this.setState({ data });
render() {
const data = [];
return <ListElement onMouseOver={() => this.debouncedMouseOver(data)}>Data</ListElement>;
}
}
您可以创建一个方法,在满足特殊要求时触发 onMouseOver
事件。
在进一步的例子中,它在500 ms
之后触发。
/**
* Hold the descriptor to the setTimeout
*/
protected timeoutOnMouseOver = false;
/**
* Method which is going to trigger the onMouseOver only once in Xms
*/
protected mouseOverTreatment(data) {
// If they were already a programmed setTimeout
// stop it, and run a new one
if (this.timeoutOnMouseOver) {
clearTimeout(this.timeoutOnMouseOver);
}
this.timeoutOnMouseOver = setTimeout(() => {
this.setState(data);
this.timeoutOnMouseOver = false;
}, 500);
}
结合使用 onMouseEnter
、onMouseLeave
和 setTimeout
.
请记住,数据的状态更新可以由父组件管理并作为 prop 传入。
import React, { useState } from 'react'
const ListElement = () => {
const [data, setData] = useState(null)
const [delayHandler, setDelayHandler] = useState(null)
const handleMouseEnter = event => {
setDelayHandler(setTimeout(() => {
const yourData = // whatever your data is
setData(yourData)
}, 500))
}
const handleMouseLeave = () => {
clearTimeout(delayHandler)
}
return (
<div
onMouseEnter={handleMouseEnter}
onMouseLeave={handleMouseLeave}
>
I have a delayed event handler
</div>
)
}
export default ListElement
debounce
如果您想在一个时间范围内限制操作,那总是答案。
实现简单,无需外部库。
实施:
type Fnc = (...args: any[]) => void;
// default 300ms delay
export function debounce<F extends Fnc>(func: F, delay = 300) {
type Args = F extends (...args: infer P) => void ? P : never;
let timeout: any;
return function (this: any, ...args: Args) {
clearTimeout(timeout);
timeout = setTimeout(() => {
func.apply(this, args);
}, delay);
};
}
用法:
...
/** any action you want to debounce */
function foo(
data: any,
event: React.MouseEvent<HTMLDivElement, MouseEvent>
): void {
this.setState({data});
}
const fooDebounced = debounce(foo, 500);
<ListElement onMouseOver={fooDebounced.bind(null, data)}>
Data
</ListElement>
...
您实际上不必 bind
一个函数,但如果您遍历多个元素以避免为每个元素初始化一个新函数,这是一个好习惯。
我可能来晚了一点,但我想使用 Lodash debounce
添加到上面的一些答案中。在对方法进行去抖动时,debounce
函数可让您根据某些事件取消对方法的调用。请参阅功能组件示例:
const [isHovered, setIsHovered] = React.useState(false)
const debouncedHandleMouseEnter = debounce(() => setIsHovered(true), 500)
const handlOnMouseLeave = () => {
setIsHovered(false)
debouncedHandleMouseEnter.cancel()
}
return (
<div
onMouseEnter={debouncedHandleMouseEnter}
onMouseLeave={handlOnMouseLeave}
>
... do something with isHovered state...
</div>
)
此示例仅在用户将鼠标悬停在您的元素中 500 毫秒后才调用您的函数,如果鼠标离开该元素,调用将被取消。