Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
July 15, 2022 06:47 am GMT

React cleaner use of setTimeout

When working with setTimeout we generally don't have to worry about cleaning up our timeouts.

However, introducing it into React can create some nasty edge-cases.

This often happens because we want to manipulate data after x time.
The component might be unmounted by then, but the timeout is still trying to activate.

You might see some edge cases where your interactions seem to be reverted.
Or even get memory leak messages in your console.

Clear your timeouts!

The general rule of advice is to keep track of the timeouts you create in your code and clean them.

To clean your timeouts, we can leverage the useEffect cleanup function.

A quick example could look like this:

export default function Test() {  const [show, setShow] = useState(false);  useEffect(() => {    const test = window.setTimeout(() => {      setShow(false);    }, 1500);    return () => {      clearInterval(test);    };  }, []);  return (    <div>      <h1>Loading...</h1>      {show && <p>I'm fully loaded now</p>}    </div>  );}

However, I prefer to use a reference to clear the interval.

const timeoutRef = useRef();useEffect(() => {  timeoutRef.current = window.setTimeout(() => {    setShow(false);  }, 1500);  return () => clearInterval(timeoutRef.current);}, []);

This will work, but it's a bit of a hassle to remember to clean this up on unmount, etc.

So why not create a small hook for it?

React useTimeout hook

We can start by introducing a useTimeout hook.
This hook will be our React version of the setTimeout function.

This hook should have the following options.

  • Receive the callback function (an action that should happen after the timeout)
  • Receive the delay (time for it to timeout)
  • Return a function that can be invoked to start it
import { useCallback, useEffect, useRef, useMemo } from 'react';export default function useTimeout(callback, delay) {  const timeoutRef = useRef();  const callbackRef = useRef(callback);  useEffect(() => {    callbackRef.current = callback;  }, [callback]);  useEffect(() => {    return () => window.clearTimeout(timeoutRef.current);  }, []);  const memoizedCallback = useCallback(    (args) => {      if (timeoutRef.current) {        window.clearTimeout(timeoutRef.current);      }      timeoutRef.current = window.setTimeout(() => {        timeoutRef.current = null;        callbackRef.current?.(args);      }, delay);    },    [delay, timeoutRef, callbackRef]  );  return useMemo(() => [memoizedCallback], [memoizedCallback]);}

First, we see the parameters passed as callback and delay.
Then we add two references to keep track of the active timeout and active callback.

Then we'll need two useEffects, the first one to listen to the callback in case it changes after rendering (this could happen if you change any state inside the callback).

The second one is used to handle the cleanup effect for the timeout. (When the component gets unmounted)

Then we create a useCallback, where we first clear out any existing timeouts in our ref.
Then we assign the new timeout. This whole callback listens to changes on all our variables.

And the last part is to return a memoized function that will listen to changes on its callback.

This might seem an overkill method, but it will help solidify your timeouts and keep everything as clean as possible.

Using the hook

To use the hook, we can introduce the following code.

import useTimeout from './useTimeout';const [timeout] = useTimeout(() => {  setShow(false);}, 1500);timeout();

Wow, way cleaner, right?
And now, we only have one place to keep track of our timeouts and ensure they are constantly cleaned up.

Thank you for reading, and let's connect!

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter


Original Link: https://dev.to/dailydevtips1/react-cleaner-use-of-settimeout-105m

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To