0

So I have a function to run async, so put async inside useEffect, in below is my code

 useEffect(() => {
    const data = async () => {
      const data = await getAllVertification();
      if (!data.status) {
      } else {
        setAlldata(data.data);
        setLoadingAction([]);
        let tmp = [];
        for (const element of data.data) {
          tmp.push({ status: false });
        }
        setLoadingAction(tmp);
      }
    };

    data();
  }, [update]);

but got waning like this

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.

Can someone explain to me ?

2
  • Does this help you? stackoverflow.com/questions/53332321/… Commented May 30, 2021 at 18:09
  • What specifically is unclear about the error/warning? Commented May 30, 2021 at 18:13

3 Answers 3

1

You'll need to cancel the operations after await resolves when the component is unmounted. Here's one of the ways to do this.

  useEffect(() => {
    let isSubscribed = true;
    const data = async () => {
      const data = await getAllVertification();
      if(isSubscribed) {
        if (!data.status) {
        } else {
          setAlldata(data.data);
          setLoadingAction([]);
          let tmp = [];
          for (const element of data.data) {
            tmp.push({ status: false });
          }
          setLoadingAction(tmp);
        }
      }
    };
    data();
    return () => (isSubscribed = false);
  }, [update]);
Sign up to request clarification or add additional context in comments.

Comments

0

rewriting you code to make it more clear:

 useEffect(() => {
    const getData = async () => {
      const data = await getAllVertification();
      if (!data.status) {
      } else {
        setAlldata(data.data);
        setLoadingAction([]);
        let tmp = [];
        for (const element of data.data) {
          tmp.push({ status: false });
        }
        setLoadingAction(tmp);
      }
    };

    getData();
  }, [update]);

Here getData is an Async function which means that when you run it it returns a promise which will be executed at the end of the current event loop cycle. You dont have to make getData though.
Try this:

 useEffect(() => {
    getAllVertification().then(data => {
      if (!data.status) {
      } else {
        setAlldata(data.data);
        setLoadingAction([]);
        let tmp = [];
        for (const element of data.data) {
          tmp.push({ status: false });
        }
        setLoadingAction(tmp);
      }
    }
  }, [update]);

Comments

0

Using a custom hook, we can do the following:

import { useAsyncEffect } from "use-async-effect2";

// ...

 useAsyncEffect(function*(){
      const data = yield getAllVertification();
      if (data.status) {
        setAlldata(data.data);
        let tmp = [];
        for (const element of data.data) { 
          tmp.push({ status: false }); // weird code
        }
        setLoadingAction(tmp);
      }
    };
  }, [update]);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.