Kyle Shevlin

Software Engineer

Snippet

useAsyncSafeState()

edit
0 strokes bestowed

If you ever find yourself calling a state setter in an async process, there's a reasonable chance that you may call it after the component unmounts and therefore incur an error indicating a memory leak in you application.

The way to solve for this is to prevent the setState call if the component has unmounted. We can track the isMounted state of a hook using a ref, and wrap the state setter to automatically check this value before making its update. Like so:

function useAsyncSafeState(value) {
  // Track the mounted state of the component using the hook
  const isMounted = React.useRef(true)

  // If the component unmounts, update the `isMounted` state
  React.useEffect(() => {
    return () => {
      isMounted.current = false
    }
  }, [])

  const [state, setState] = React.useState(value)

  // Prevent `setState` calls after the component unmounts
  const safeSetState = React.useCallback(update => {
    if (isMounted.current) {
      setState(update)
    }
  }, [])

  return [state, safeSetState]
}

Now you can make use of this in a situation where there's a chance that component unmounts before the state is set. Like fetching data:

function MyComp() {
  const [data, setData] = useAsyncSafeState(null)

  React.useEffect(() => {
    function getData() {
      fetch('/path/to/data')
        .then(result => {
          setData(result)
        })
        .catch(console.error)
    }

    getData()
  }, [setData]) // linter will not know that this is stable.

  return (
    data && (
      <pre>
        <code>{JSON.stringify(data, null, 2)}</code>
      </pre>
    )
  )
}

If the user leaves the page with MyComp or its unmounted for some other reason, setData won't create an error.


Finished reading?

Here are a few options for what to do next.

Like
Liked the post? Click the beard up to 50 times to show it
Share
Sharing this post on Twitter & elsewhere is a great way to help me out

Kyle Shevlin's face, which is mostly a beard with eyes
Kyle Shevlin is a software engineer who specializes in JavaScript, React and front end web development.

Let's talk some more about JavaScript, React, and software engineering.

I write a newsletter to share my thoughts and the projects I'm working on. I would love for you to join the conversation. You can unsubscribe at any time.

Just Enough Functional Programming Logo
Just Enough Functional Programming

Check out my courses!

Liked the post? You might like my courses, too. Click the button to view this course or go to Courses for more information.
I would like give thanks to those who have contributed fixes and updates to this blog. If you see something that needs some love, you can join them. This blog is open sourced at https://github.com/kyleshevlin/blog
alexloudenjacobwsmithbryndymentJacobMGEvanseclectic-codingjhsukgcreativeerikvorhesHaroenvmarktnoonandependabotmarcuslyonsbrentmclarkfederico-fiorinimedayzDoNormalFanchGadjonoahmateenbrandonpittman
©2022 Kyle Shevlin. All Rights Reserved.