How to Properly Use setTimeout in React

Ferenc Almasi β€’ 2022 September 09 β€’ Read time 4 min read
  • twitter
  • facebook
React

In order to properly call setTimeout in React (and ensure it is only called once), you need to wrap your call inside a useEffect hook:

Copied to clipboard! Playground
useEffect(() => {
    const timeout = setTimeout(() => {
        console.log('Called after 1 sec!')
    }, 1000)
 
    return () => clearTimeout(timeout)
}, [])

If you were to call the setTimeout outside a useEffect hook anywhere in your component, then this would rerun on every render.

Another important step is to always clear the timeout after the component unmounts, which you can do by returning a function from the useEffect hook. This is the equivalent of using componentWillUnmount in a class-based component.

Here we can call the clearTimeout function and pass our reference to the setTimeout in order to properly free up memory and remove the timeout.


Using State in setTimeout

Using state with setTimeout can sometimes be tricky. Imagine you have an input field with a submit button that delays the action by 1 second using a setTimeout.

Copied to clipboard! Playground
import { useState } from 'react'

export default function App() {
    const [email, setEmail] = useState('')

    const submit = () => {
        setTimeout(() => {
            console.log(email)
        }, 1000)
    }

    return (
        <div>
            <input onChange={event => setEmail(event.target.value)} />
            <button onClick={submit}>Submit</button>
        </div>
    )
}

If you fill in the input and click on submit, then the value of the input will be logged to the console after one second, just as expected. But what happens if you update the input field after you clicked the button?

In this case, you will still get the value logged, but not the latest value. You will get the value logged out that was available in the input when you clicked on the button. In order to get around this, we need to use refs. Take a look at how our component changes now:

Copied to clipboard! Playground
import { useRef, useState, useEffect } from 'react'

export default function App() {
    const emailRef = useRef('')
    const [email, setEmail] = useState('')

    useEffect(() => {
        emailRef.current = email
    }, [email])

    const submit = () => {
        setTimeout(() => {
            console.log(emailRef.current)
        }, 1000)
    }

    return (
        <div>
            <input onChange={event => setEmail(event.target.value)} />
            <button onClick={submit}>Submit</button>
        </div>
    )
}

We introduced a new ref using the useRef hook, and assign its current value to email inside a useEffect hook. Notice that you also want to add email as a dependency inside the dependency array.

Now inside the setTimeout, we log out emailRef.current instead of email. This way, you will always have the latest value available to you even inside the setTimeout.


Creating a useTimeout hook

Lastly, let's take a look at how you can create a useTimeout hook that you can later reuse inside your other components.

Copied to clipboard! Playground
export const useTimeout = (callback, timeout) => {
  useEffect(() => {
    const timeoutReference = setTimeout(callback, timeout);
 
    return () => clearTimeout(timeoutReference);
   }, [])
}

This hook expects a callback function as well as a timeout, just like setTimeout, but it is wrapped inside a useEffect hook in order to ensure we only call it once. The hook also ensures that the timeout is cleared after the component unmounts. To use it inside a component, you can call it like so:

Copied to clipboard! Playground
import { useState } from 'react'
import { useTimeout } from '@hooks'

export default function App() {
    useTimeout(() => {
        console.log('Called after 1 sec!')
    }, 1000)

    return ...
}
  • twitter
  • facebook
React
Did you find this page helpful?
πŸ“š More Webtips
Frontend Course Dashboard
Master the Art of Frontend
  • check Access 100+ interactive lessons
  • check Unlimited access to hundreds of tutorials
  • check Prepare for technical interviews
Become a Pro

Courses

Recommended

This site uses cookies We use cookies to understand visitors and create a better experience for you. By clicking on "Accept", you accept its use. To find out more, please see our privacy policy.