← Back to React Course | Chapter 10: Data Fetching & Async | Lesson 3 of 10

useEffect के अंदर async/await

useEffect के अंदर async/await उपयोग करना एक helper को coffee लाने भेजने और straight वापस आकर report करने को कहने जैसा है, उन्हें एक note छोड़ने के बजाय जो वे कभी भी पढ़ सकते हैं।
Syntax
markup
useEffect(() => {
  async function loadData() {
    try {
      const response = await fetch(url);
      const data = await response.json();
      setData(data);
    } catch (error) {
      setError(error);
    }
  }
  loadData();
}, [url]);

useEffect का Callback Directly async क्यों नहीं हो सकता

useEffect अपने callback से यह expect करता है कि वह कुछ न return करे, या एक cleanup function return करे। एक async function हमेशा एक Promise return करता है, जिसे React एक valid cleanup function के रूप में interpret नहीं कर सकता, इसलिए effect callback को खुद async बनाना एक warning trigger करता है और सही से काम नहीं करता।

Note: Fix simple है: effect के अंदर एक separate async function define करें, फिर इसे immediately call करें, outer effect callback को खुद synchronous रखते हुए।
Warning: useEffect(async () => {...}) लिखना देखने में काम करना चाहिए जैसा लगता है लेकिन एक React warning produce करता है कि एक effect cleanup function के बजाय एक Promise return कर रहा है।

उदाहरण: Why useEffect's Callback Can't Be async Directly

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
function App() {
  const [data, setData] = React.useState(null);
  React.useEffect(() => {
    async function load() {
      const result = "Loaded via inner async function";
      setData(result);
    }
    load();
  }, []);
  return <p>{data || "Loading..."}</p>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
  </script>
</body>
</html>

try/catch से Errors Handle करना

चूंकि inner async function await उपयोग करता है, awaited calls को try/catch में wrap करना आपको rejected promises (जैसे एक failed fetch) को उसी जगह handle करने देता है, एक error state set करते हुए जो component display कर सके, rejection को unnoticed disappear होने देने के बजाय।

Note: Errors को जहां वे होते हैं उसके जितना possible हो पास catch करें — inner async function के अंदर, outer effect में नहीं।
Warning: बिना try/catch के, एक rejected awaited promise एक unhandled promise rejection बन जाता है, user के लिए invisible और development के दौरान miss करना easy।

उदाहरण: Handling Errors with try/catch

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
function App() {
  const [error, setError] = React.useState(null);
  React.useEffect(() => {
    async function load() {
      try {
        throw new Error("Simulated failure");
      } catch (err) {
        setError(err.message);
      }
    }
    load();
  }, []);
  return <p style={{color: "red"}}>{error || "No errors"}</p>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
  </script>
</body>
</html>

Unmount के बाद Updates से Guard करना

अगर एक slow async call finish होने से पहले component unmount हो जाए, तो बाद में setState call करना एक React warning log करता है। एक boolean flag, जो effect के cleanup function में true set होता है, async function को state update करने से पहले यह check करने देता है कि अब भी ऐसा करना safe है या नहीं।

Note: cancelled flag को async function के अंदर हर setState call से ठीक पहले check करें, सिर्फ top पर एक बार नहीं।
Warning: इस guard को skip करना fast requests के लिए mostly harmless है, लेकिन उन slow requests के लिए एक real issue बन जाता है जिन pages से users जल्दी navigate away करते हैं।

उदाहरण: Guarding Against Updates After Unmount

markup
<!DOCTYPE html>
<html>
<head>
  <script src="https://unpkg.com/react@18/umd/react.development.js"></script>
  <script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
</head>
<body>
  <div id="root"></div>
  <script type="text/babel">
function App() {
  const [data, setData] = React.useState(null);
  React.useEffect(() => {
    let cancelled = false;
    async function load() {
      const result = "Safely loaded";
      if (!cancelled) setData(result);
    }
    load();
    return () => { cancelled = true; };
  }, []);
  return <p>{data || "Loading..."}</p>;
}
ReactDOM.createRoot(document.getElementById('root')).render(<App />);
  </script>
</body>
</html>
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
आम गलतियां
  1. useEffect callback को खुद async बनाना, जिसे React support नहीं करता — callback को void या एक cleanup function return करना चाहिए, कोई Promise नहीं।
  2. एक slow async call के दौरान component unmount होने पर state set करने से guard करना भूल जाना।
  3. Awaited promise के rejected case को handle न करना, errors को silently disappear होने देते हुए।
चैप्टर सारांश
  • useEffect का callback function directly async declare नहीं किया जा सकता — React इससे void या एक cleanup function return करने की expectation रखता है।
  • Standard workaround है effect के INSIDE एक async function define करना और इसे immediately call करना।
  • Awaited calls के around try/catch उन errors को handle करता है जिन्हें एक plain .then() chain silently drop कर सकती है।
  • एक cancelled flag component unmount होने के बाद state update करने से guard करता है।
ब्राउज़र सपोर्ट

async/await और useEffect दोनों broadly supported हैं (ES2017+ syntax, React 16.8+ Hooks)।

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.