0

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.

callmenikk
  • 1,358
  • 2
  • 9
  • 24
  • 1
    The fetch request is slow, and the component has already unmounted when the async request finishes. Check this out: https://dev.to/pallymore/clean-up-async-requests-in-useeffect-hooks-90h – Tasos Tsournos Jan 12 '22 at 20:12
  • 2
    One question you should ask is, does it matter? Yes, you can prevent the `setUserBlog()` call if you're no longer mounted, but one issue is that you add code with only 1 benefit: the warning goes away. Except if you use the abort controller. Using that you *can* reduce some work, but I don't see you passing it to axios. – Evert Jan 12 '22 at 20:13

1 Answers1

3

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()
Bastiat
  • 657
  • 1
  • 6
  • 18
  • it worked, but state stay empty, is there any chance to keep state updated and also cancel fetching – callmenikk Jan 12 '22 at 20:24
  • @callmenikk what do you mean keep the state? if we cancel the fetch then we havent loaded anything yet? – Bastiat Jan 12 '22 at 20:27
  • @Basiat yes, you are right, but can I make something like that to update state and also don't get that error about memory leak – callmenikk Jan 12 '22 at 20:28
  • 1
    The memory leak warning is happening because you are attempting to update state in an unmounted component, so you arent going to be able to allow the call to complete and get the data if the component is unmounted. If you need that elsewhere, then you can move the call to a component higher in the tree that 1) doesnt get unmounted and 2) is a parent of all children that need it – Bastiat Jan 13 '22 at 13:30