just test
just test

Reputation: 383

async inside useEffect react

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 ?

Upvotes: 0

Views: 65

Answers (3)

Dmitriy Mozgovoy
Dmitriy Mozgovoy

Reputation: 1597

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]);

Upvotes: 0

Prayag Choraria
Prayag Choraria

Reputation: 819

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]);

Upvotes: 1

michmich112
michmich112

Reputation: 774

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]);

Upvotes: 0

Related Questions