DEV Community

Zach
Zach

Posted on

Memory Leaks

In this post:

  1. The Problem
  2. What's a Memory Leak?
  3. The Solution

Hooks are (is?) still pretty new to me. But since it seems like an important feature of React to understand, I've stretched to use it in my projects and start to gain some practical knowledge.

The most creative implementation that I've attempted so far is wrapping the useEffect hook inside of a custom hook that fetches a blog post from my Blog Model.

Here's what it looked like:

const usePostData = (user, postId) => {

  const [post, setPost] = useState([]);

  useEffect(()=>{
    httpHandler.getPost(user, postId, (err, data)=>{
      setPost(data)
    })
  },[])
  return post
}
Enter fullscreen mode Exit fullscreen mode

I used this function to populate a Post component with data:

const post = usePostData(user, post_id)
Enter fullscreen mode Exit fullscreen mode

The Problem

React didn't like this, and it threw the following error:

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.

I did a little reading and found some great resources that explained the issue and provided solution for fixing the memory leak:

What's a Memory Leak?

Put simply, a memory leak is created when data is requested, but has nowhere to go.

In React, this can occur when the feature that is requesting the data unmounts before the data is delivered. This isn't uncommon when making asynchronous calls like over http.

I have some work to do to determine what unmounts in my Post component code, and why. Does it unmount and then remount on render when the data actually reaches the component? No - my understanding is that it mounts on the first render. So when does it unmount? That will remain a mystery until tomorrow.

The Solution

In the meantime, here's the code after applying the most straightforward solution that all three resources provided:

const usePostData = (user, postId) => {

  const [post, setPost] = useState();

  useEffect(()=>{
    let componentMounted = true;
    httpHandler.getPost(user, postId, (err, data)=>{
      if (componentMounted){
      setPost(data)
      }
    })
    return () => {
      componentMounted = false
    }
  },[])
  return post
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)