React Hook Warnings for async function in useEffect: useEffect function must return a cleanup function or...












11















I was trying the useEffect example something like below:






useEffect(async () => {
try {
const response = await fetch(`https://www.reddit.com/r/${subreddit}.json`);
const json = await response.json();
setPosts(json.data.children.map(it => it.data));
} catch (e) {
console.error(e);
}
}, );





and I get this warning in my console. But the cleanup is optional for async calls I think. I am not sure why I get this warning. Linking sandbox for examples. https://codesandbox.io/s/24rj871r0p
enter image description here










share|improve this question





























    11















    I was trying the useEffect example something like below:






    useEffect(async () => {
    try {
    const response = await fetch(`https://www.reddit.com/r/${subreddit}.json`);
    const json = await response.json();
    setPosts(json.data.children.map(it => it.data));
    } catch (e) {
    console.error(e);
    }
    }, );





    and I get this warning in my console. But the cleanup is optional for async calls I think. I am not sure why I get this warning. Linking sandbox for examples. https://codesandbox.io/s/24rj871r0p
    enter image description here










    share|improve this question



























      11












      11








      11


      3






      I was trying the useEffect example something like below:






      useEffect(async () => {
      try {
      const response = await fetch(`https://www.reddit.com/r/${subreddit}.json`);
      const json = await response.json();
      setPosts(json.data.children.map(it => it.data));
      } catch (e) {
      console.error(e);
      }
      }, );





      and I get this warning in my console. But the cleanup is optional for async calls I think. I am not sure why I get this warning. Linking sandbox for examples. https://codesandbox.io/s/24rj871r0p
      enter image description here










      share|improve this question
















      I was trying the useEffect example something like below:






      useEffect(async () => {
      try {
      const response = await fetch(`https://www.reddit.com/r/${subreddit}.json`);
      const json = await response.json();
      setPosts(json.data.children.map(it => it.data));
      } catch (e) {
      console.error(e);
      }
      }, );





      and I get this warning in my console. But the cleanup is optional for async calls I think. I am not sure why I get this warning. Linking sandbox for examples. https://codesandbox.io/s/24rj871r0p
      enter image description here






      useEffect(async () => {
      try {
      const response = await fetch(`https://www.reddit.com/r/${subreddit}.json`);
      const json = await response.json();
      setPosts(json.data.children.map(it => it.data));
      } catch (e) {
      console.error(e);
      }
      }, );





      useEffect(async () => {
      try {
      const response = await fetch(`https://www.reddit.com/r/${subreddit}.json`);
      const json = await response.json();
      setPosts(json.data.children.map(it => it.data));
      } catch (e) {
      console.error(e);
      }
      }, );






      javascript reactjs react-hooks






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 16 '18 at 7:05









      skyboyer

      4,19811333




      4,19811333










      asked Nov 16 '18 at 6:07









      RedPandazRedPandaz

      338413




      338413
























          3 Answers
          3






          active

          oldest

          votes


















          15














          I suggest to look at Dan Abramov (one of the react creators) answer here:




          I think you're making it more complicated than it needs to be.




          async function fetchMyAPI() {
          let url = 'http://something';
          let config = {};
          const response = await myFetch(url);
          console.log(response);
          }

          useEffect(() => {
          fetchMyAPI();
          }, );



          Longer term we'll discourage this pattern because it encourages race conditions. Such as — anything could happen between your call starts and ends, and you could have gotten new props. Instead, we'll recommend Suspense for data fetching which will look more like




          const response = MyAPIResource.read();



          and no effects. But in the meantime you can move the async stuff to a separate function and call it.







          share|improve this answer


























          • You could solve the race condition issues by checking if the component is unmounted like so: useEffect(() => { let unmounted = false promise.then(res => { if (!unmounted) { setState(...) } }) return () => { unmounted = true } }, )

            – Richard
            Feb 28 at 11:06





















          18














          When you use an async function like



          async () => {
          try {
          const response = await fetch(`https://www.reddit.com/r/${subreddit}.json`);
          const json = await response.json();
          setPosts(json.data.children.map(it => it.data));
          } catch (e) {
          console.error(e);
          }
          }


          it returns a promise and useEffect doesn't expect the callback function to return Promise, rather it expects that nothing is returned or a function is returned.



          As a workaround for the warning you can use a self invoking async function.



          useEffect(() => {
          (async function() {
          try {
          const response = await fetch(
          `https://www.reddit.com/r/${subreddit}.json`
          );
          const json = await response.json();
          setPosts(json.data.children.map(it => it.data));
          } catch (e) {
          console.error(e);
          }
          })();
          }, );


          or to make it more cleaner you could define a function and then call it



          useEffect(() => {
          async function fetchData() {
          try {
          const response = await fetch(
          `https://www.reddit.com/r/${subreddit}.json`
          );
          const json = await response.json();
          setPosts(json.data.children.map(it => it.data));
          } catch (e) {
          console.error(e);
          }
          };
          fetchData();
          }, );


          the second solution will make it easier to read and will help you write code to cancel previous requests if a new one is fired or save the latest request response in state



          Working codesandbox






          share|improve this answer


























          • A package to make this easier has been made. You can find it here.

            – KittyCat
            Nov 27 '18 at 12:12











          • but eslint won't tolerate with that

            – Muhaimin CS
            Jan 10 at 7:02



















          10














          Until React provides a better way, you can create a helper, useEffectAsync.js:



          import { useEffect } from 'react';


          export default function useEffectAsync(effect, inputs) {
          useEffect(() => {
          effect();
          }, inputs);
          }


          Now you can pass an async function:



          useEffectAsync(async () => {
          const items = await fetchSomeItems();
          console.log(items);
          }, );





          share|improve this answer
























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53332321%2freact-hook-warnings-for-async-function-in-useeffect-useeffect-function-must-ret%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            3 Answers
            3






            active

            oldest

            votes








            3 Answers
            3






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            15














            I suggest to look at Dan Abramov (one of the react creators) answer here:




            I think you're making it more complicated than it needs to be.




            async function fetchMyAPI() {
            let url = 'http://something';
            let config = {};
            const response = await myFetch(url);
            console.log(response);
            }

            useEffect(() => {
            fetchMyAPI();
            }, );



            Longer term we'll discourage this pattern because it encourages race conditions. Such as — anything could happen between your call starts and ends, and you could have gotten new props. Instead, we'll recommend Suspense for data fetching which will look more like




            const response = MyAPIResource.read();



            and no effects. But in the meantime you can move the async stuff to a separate function and call it.







            share|improve this answer


























            • You could solve the race condition issues by checking if the component is unmounted like so: useEffect(() => { let unmounted = false promise.then(res => { if (!unmounted) { setState(...) } }) return () => { unmounted = true } }, )

              – Richard
              Feb 28 at 11:06


















            15














            I suggest to look at Dan Abramov (one of the react creators) answer here:




            I think you're making it more complicated than it needs to be.




            async function fetchMyAPI() {
            let url = 'http://something';
            let config = {};
            const response = await myFetch(url);
            console.log(response);
            }

            useEffect(() => {
            fetchMyAPI();
            }, );



            Longer term we'll discourage this pattern because it encourages race conditions. Such as — anything could happen between your call starts and ends, and you could have gotten new props. Instead, we'll recommend Suspense for data fetching which will look more like




            const response = MyAPIResource.read();



            and no effects. But in the meantime you can move the async stuff to a separate function and call it.







            share|improve this answer


























            • You could solve the race condition issues by checking if the component is unmounted like so: useEffect(() => { let unmounted = false promise.then(res => { if (!unmounted) { setState(...) } }) return () => { unmounted = true } }, )

              – Richard
              Feb 28 at 11:06
















            15












            15








            15







            I suggest to look at Dan Abramov (one of the react creators) answer here:




            I think you're making it more complicated than it needs to be.




            async function fetchMyAPI() {
            let url = 'http://something';
            let config = {};
            const response = await myFetch(url);
            console.log(response);
            }

            useEffect(() => {
            fetchMyAPI();
            }, );



            Longer term we'll discourage this pattern because it encourages race conditions. Such as — anything could happen between your call starts and ends, and you could have gotten new props. Instead, we'll recommend Suspense for data fetching which will look more like




            const response = MyAPIResource.read();



            and no effects. But in the meantime you can move the async stuff to a separate function and call it.







            share|improve this answer















            I suggest to look at Dan Abramov (one of the react creators) answer here:




            I think you're making it more complicated than it needs to be.




            async function fetchMyAPI() {
            let url = 'http://something';
            let config = {};
            const response = await myFetch(url);
            console.log(response);
            }

            useEffect(() => {
            fetchMyAPI();
            }, );



            Longer term we'll discourage this pattern because it encourages race conditions. Such as — anything could happen between your call starts and ends, and you could have gotten new props. Instead, we'll recommend Suspense for data fetching which will look more like




            const response = MyAPIResource.read();



            and no effects. But in the meantime you can move the async stuff to a separate function and call it.








            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Feb 18 at 16:00

























            answered Dec 1 '18 at 16:02









            RTWRTW

            784218




            784218













            • You could solve the race condition issues by checking if the component is unmounted like so: useEffect(() => { let unmounted = false promise.then(res => { if (!unmounted) { setState(...) } }) return () => { unmounted = true } }, )

              – Richard
              Feb 28 at 11:06





















            • You could solve the race condition issues by checking if the component is unmounted like so: useEffect(() => { let unmounted = false promise.then(res => { if (!unmounted) { setState(...) } }) return () => { unmounted = true } }, )

              – Richard
              Feb 28 at 11:06



















            You could solve the race condition issues by checking if the component is unmounted like so: useEffect(() => { let unmounted = false promise.then(res => { if (!unmounted) { setState(...) } }) return () => { unmounted = true } }, )

            – Richard
            Feb 28 at 11:06







            You could solve the race condition issues by checking if the component is unmounted like so: useEffect(() => { let unmounted = false promise.then(res => { if (!unmounted) { setState(...) } }) return () => { unmounted = true } }, )

            – Richard
            Feb 28 at 11:06















            18














            When you use an async function like



            async () => {
            try {
            const response = await fetch(`https://www.reddit.com/r/${subreddit}.json`);
            const json = await response.json();
            setPosts(json.data.children.map(it => it.data));
            } catch (e) {
            console.error(e);
            }
            }


            it returns a promise and useEffect doesn't expect the callback function to return Promise, rather it expects that nothing is returned or a function is returned.



            As a workaround for the warning you can use a self invoking async function.



            useEffect(() => {
            (async function() {
            try {
            const response = await fetch(
            `https://www.reddit.com/r/${subreddit}.json`
            );
            const json = await response.json();
            setPosts(json.data.children.map(it => it.data));
            } catch (e) {
            console.error(e);
            }
            })();
            }, );


            or to make it more cleaner you could define a function and then call it



            useEffect(() => {
            async function fetchData() {
            try {
            const response = await fetch(
            `https://www.reddit.com/r/${subreddit}.json`
            );
            const json = await response.json();
            setPosts(json.data.children.map(it => it.data));
            } catch (e) {
            console.error(e);
            }
            };
            fetchData();
            }, );


            the second solution will make it easier to read and will help you write code to cancel previous requests if a new one is fired or save the latest request response in state



            Working codesandbox






            share|improve this answer


























            • A package to make this easier has been made. You can find it here.

              – KittyCat
              Nov 27 '18 at 12:12











            • but eslint won't tolerate with that

              – Muhaimin CS
              Jan 10 at 7:02
















            18














            When you use an async function like



            async () => {
            try {
            const response = await fetch(`https://www.reddit.com/r/${subreddit}.json`);
            const json = await response.json();
            setPosts(json.data.children.map(it => it.data));
            } catch (e) {
            console.error(e);
            }
            }


            it returns a promise and useEffect doesn't expect the callback function to return Promise, rather it expects that nothing is returned or a function is returned.



            As a workaround for the warning you can use a self invoking async function.



            useEffect(() => {
            (async function() {
            try {
            const response = await fetch(
            `https://www.reddit.com/r/${subreddit}.json`
            );
            const json = await response.json();
            setPosts(json.data.children.map(it => it.data));
            } catch (e) {
            console.error(e);
            }
            })();
            }, );


            or to make it more cleaner you could define a function and then call it



            useEffect(() => {
            async function fetchData() {
            try {
            const response = await fetch(
            `https://www.reddit.com/r/${subreddit}.json`
            );
            const json = await response.json();
            setPosts(json.data.children.map(it => it.data));
            } catch (e) {
            console.error(e);
            }
            };
            fetchData();
            }, );


            the second solution will make it easier to read and will help you write code to cancel previous requests if a new one is fired or save the latest request response in state



            Working codesandbox






            share|improve this answer


























            • A package to make this easier has been made. You can find it here.

              – KittyCat
              Nov 27 '18 at 12:12











            • but eslint won't tolerate with that

              – Muhaimin CS
              Jan 10 at 7:02














            18












            18








            18







            When you use an async function like



            async () => {
            try {
            const response = await fetch(`https://www.reddit.com/r/${subreddit}.json`);
            const json = await response.json();
            setPosts(json.data.children.map(it => it.data));
            } catch (e) {
            console.error(e);
            }
            }


            it returns a promise and useEffect doesn't expect the callback function to return Promise, rather it expects that nothing is returned or a function is returned.



            As a workaround for the warning you can use a self invoking async function.



            useEffect(() => {
            (async function() {
            try {
            const response = await fetch(
            `https://www.reddit.com/r/${subreddit}.json`
            );
            const json = await response.json();
            setPosts(json.data.children.map(it => it.data));
            } catch (e) {
            console.error(e);
            }
            })();
            }, );


            or to make it more cleaner you could define a function and then call it



            useEffect(() => {
            async function fetchData() {
            try {
            const response = await fetch(
            `https://www.reddit.com/r/${subreddit}.json`
            );
            const json = await response.json();
            setPosts(json.data.children.map(it => it.data));
            } catch (e) {
            console.error(e);
            }
            };
            fetchData();
            }, );


            the second solution will make it easier to read and will help you write code to cancel previous requests if a new one is fired or save the latest request response in state



            Working codesandbox






            share|improve this answer















            When you use an async function like



            async () => {
            try {
            const response = await fetch(`https://www.reddit.com/r/${subreddit}.json`);
            const json = await response.json();
            setPosts(json.data.children.map(it => it.data));
            } catch (e) {
            console.error(e);
            }
            }


            it returns a promise and useEffect doesn't expect the callback function to return Promise, rather it expects that nothing is returned or a function is returned.



            As a workaround for the warning you can use a self invoking async function.



            useEffect(() => {
            (async function() {
            try {
            const response = await fetch(
            `https://www.reddit.com/r/${subreddit}.json`
            );
            const json = await response.json();
            setPosts(json.data.children.map(it => it.data));
            } catch (e) {
            console.error(e);
            }
            })();
            }, );


            or to make it more cleaner you could define a function and then call it



            useEffect(() => {
            async function fetchData() {
            try {
            const response = await fetch(
            `https://www.reddit.com/r/${subreddit}.json`
            );
            const json = await response.json();
            setPosts(json.data.children.map(it => it.data));
            } catch (e) {
            console.error(e);
            }
            };
            fetchData();
            }, );


            the second solution will make it easier to read and will help you write code to cancel previous requests if a new one is fired or save the latest request response in state



            Working codesandbox







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Mar 27 at 7:42

























            answered Nov 16 '18 at 6:11









            Shubham KhatriShubham Khatri

            94.3k15119160




            94.3k15119160













            • A package to make this easier has been made. You can find it here.

              – KittyCat
              Nov 27 '18 at 12:12











            • but eslint won't tolerate with that

              – Muhaimin CS
              Jan 10 at 7:02



















            • A package to make this easier has been made. You can find it here.

              – KittyCat
              Nov 27 '18 at 12:12











            • but eslint won't tolerate with that

              – Muhaimin CS
              Jan 10 at 7:02

















            A package to make this easier has been made. You can find it here.

            – KittyCat
            Nov 27 '18 at 12:12





            A package to make this easier has been made. You can find it here.

            – KittyCat
            Nov 27 '18 at 12:12













            but eslint won't tolerate with that

            – Muhaimin CS
            Jan 10 at 7:02





            but eslint won't tolerate with that

            – Muhaimin CS
            Jan 10 at 7:02











            10














            Until React provides a better way, you can create a helper, useEffectAsync.js:



            import { useEffect } from 'react';


            export default function useEffectAsync(effect, inputs) {
            useEffect(() => {
            effect();
            }, inputs);
            }


            Now you can pass an async function:



            useEffectAsync(async () => {
            const items = await fetchSomeItems();
            console.log(items);
            }, );





            share|improve this answer




























              10














              Until React provides a better way, you can create a helper, useEffectAsync.js:



              import { useEffect } from 'react';


              export default function useEffectAsync(effect, inputs) {
              useEffect(() => {
              effect();
              }, inputs);
              }


              Now you can pass an async function:



              useEffectAsync(async () => {
              const items = await fetchSomeItems();
              console.log(items);
              }, );





              share|improve this answer


























                10












                10








                10







                Until React provides a better way, you can create a helper, useEffectAsync.js:



                import { useEffect } from 'react';


                export default function useEffectAsync(effect, inputs) {
                useEffect(() => {
                effect();
                }, inputs);
                }


                Now you can pass an async function:



                useEffectAsync(async () => {
                const items = await fetchSomeItems();
                console.log(items);
                }, );





                share|improve this answer













                Until React provides a better way, you can create a helper, useEffectAsync.js:



                import { useEffect } from 'react';


                export default function useEffectAsync(effect, inputs) {
                useEffect(() => {
                effect();
                }, inputs);
                }


                Now you can pass an async function:



                useEffectAsync(async () => {
                const items = await fetchSomeItems();
                console.log(items);
                }, );






                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Feb 11 at 19:27









                Ed IEd I

                4,23423039




                4,23423039






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53332321%2freact-hook-warnings-for-async-function-in-useeffect-useeffect-function-must-ret%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Florida Star v. B. J. F.

                    Danny Elfman

                    Lugert, Oklahoma