Fixing async/await in useEffect: A React Gotcha

𝗪𝗵𝘆 𝗰𝗮𝗻’𝘁 𝘄𝗲 𝘂𝘀𝗲 async/await 𝗱𝗶𝗿𝗲𝗰𝘁𝗹𝘆 𝗶𝗻𝘀𝗶𝗱𝗲 useEffect? Most of them try writing useEffect like this: useEffect(async () => {  const data = await fetchData();  setData(data); }, []); At first glance, it looks perfectly fine. But React will show a warning. What’s the reason? The function passed to useEffect must return either: • 𝗡𝗼𝘁𝗵𝗶𝗻𝗴 • 𝗔 𝗰𝗹𝗲𝗮𝗻𝘂𝗽 𝗳𝘂𝗻𝗰𝘁𝗶𝗼𝗻 E̲x̲a̲m̲pl̲e̲ ̲o̲f̲ ̲a̲ ̲c̲l̲e̲a̲n̲u̲p ̲f̲u̲n̲c̲t̲i̲o̲n̲:̲ useEffect(() => {  const id = setInterval(() => {   console.log("running...");  }, 1000);  return () => clearInterval(id); }, []); React uses the cleanup function to 𝗿𝗲𝗺𝗼𝘃𝗲 𝘀𝗶𝗱𝗲 𝗲𝗳𝗳𝗲𝗰𝘁𝘀 when: • the component unmounts • the effect runs again The problem with async When you write:useEffect(async () => {}) The function automatically returns a 𝗣𝗿𝗼𝗺𝗶𝘀𝗲. But React expects a 𝗰𝗹𝗲𝗮𝗻𝘂𝗽 𝗳𝘂𝗻𝗰𝘁𝗶𝗼𝗻, not a Promise. So React doesn’t know how to handle it. C̲o̲r̲r̲e̲c̲t̲ ̲P̲a̲t̲t̲e̲r̲n̲ Instead, define the async function 𝗶𝗻𝘀𝗶𝗱𝗲 𝘁𝗵𝗲 𝗲𝗳𝗳𝗲𝗰𝘁: useEffect(() => {  const fetchData = async () => {   const data = await getUsers();   setUsers(data);  };  fetchData(); }, []); Now the useEffect function itself remains 𝘀𝘆𝗻𝗰𝗵𝗿𝗼𝗻𝗼𝘂𝘀, which is exactly what React expects. Key Takeaway Instead of memorizing the workaround, understand 𝗵𝗼𝘄 𝗥𝗲𝗮𝗰𝘁 𝗺𝗮𝗻𝗮𝗴𝗲𝘀 𝘀𝗶𝗱𝗲 𝗲𝗳𝗳𝗲𝗰𝘁𝘀 𝗮𝗻𝗱 𝗰𝗹𝗲𝗮𝗻𝘂𝗽 𝗳𝘂𝗻𝗰𝘁𝗶𝗼𝗻𝘀. That small concept helps avoid many bugs in real-world applications. #React #ReactJS #FrontendDevelopment #JavaScript #WebDevelopment #CodingInterview #SoftwareEngineering

To view or add a comment, sign in

Explore content categories