Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delay React onMouseOver event

I have a list of elements, when hovering one of these, I'd like to change my state.

<ListElement onMouseOver={() => this.setState({data})}>Data</ListElement>

Unfortunately, if I move my mouse over the list, my state changes several times in a quick succession. I'd like to delay the change on state, so that it waits like half a second before being fired. Is there a way to do so?

like image 989
Pierre Olivier Tran Avatar asked May 22 '18 11:05

Pierre Olivier Tran


2 Answers

Here's a way you can delay your event by 500ms using a combination of onMouseEnter, onMouseLeave, and setTimeout.

Keep in mind the state update for your data could be managed by a parent component and passed in as a 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
like image 137
Ian Smith Avatar answered Sep 17 '22 17:09

Ian Smith


I might be a little late for this but I'd like to add to some of the answers above using Lodash debounce. When debouncing a method, the debounce function lets you cancel the call to your method based on some event. See example for functional component:

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>
)

This example lets you call your function only once the user is hovering in your element for 500ms, if the mouse leaves the element the call is canceled.

like image 42
Adriel Tosi Avatar answered Sep 17 '22 17:09

Adriel Tosi