Search code examples
reactjstypescriptaxiosunmount

How to stop memory leak on unmounted component


I'm trying to fetch data using axios and insert that fetched data in my useState hook, which must be array, but there is error about memory leak, I tried everything, using clean up functions also I tried new AbortController(); to cancel fetching, also tried to put isMount boolean variable to stop that error but it was still popping up same error

here is my component code everything is simple

import { useEffect, useState, FC, useRef } from "react"
import Card from "../Dashboard/Card"
import axios from "axios"
import "../../less/profile-styles/user-blogs-styles.css"
import "../../less/dashboard-style/loader.css"

const UserBlogs: FC<{ id: string; name: string }> = ({ name, id }) => {
  const [userBlogs, setUserBlogs] = useState<any>([])
  const [isLoading, setIsLoading] = useState<boolean>(false)

  useEffect(() => {

    let abortController = new AbortController();
    // let isMinted: boolean = true

    setIsLoading(true)
    axios
      .get(`http://localhost:5000/blog/blog-user/${id}`)
      .then((response) => {  //also I inserted here if statement, to check if isMunted true or not, if it true perform that inserting data in useState
          setUserBlogs(
            response.data.map((blog: any) => {
              return {
                title: blog.blog.title,
                img: blog.blog.file,
                liked: blog.blog.likes,
                mainContent: blog.blog.mainContent,
                authorID: blog.userID,
                blogId: blog.blog._id
              }
            })
          )
        
        setIsLoading(false)
      })
      .catch((err) => console.log(err))


    return () => {
      abortController.abort()
      //isMunted = false
    }
  }, [])

  console.log(userBlogs)

  return (
    <div className="user-blogs">
      <h1>{name}'s blogs</h1>
      <div className="dashboard-container">
      {
          userBlogs.map((blog: any) => {
            return (
              <Card
                title={blog.title}
                img={blog.img}
                liked={blog.likes}
                mainContent={blog.mainContent}
                authorID={blog.userId}
                blogId={blog._id}
                likeSystem={() => {}}
              />)
            }
          )
        }
      </div>
    </div>
  )
}

export default UserBlogs

here is error

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.


Solution

  • You arent actually setting the abortcontroller.signal to your axios.get call.

    See these axios docs

    axios.get('/foo/bar', {
        signal: abortController.signal
    }).then(...)
    ...
    abortController.abort()