<p><i>{bio ?? 'Loading...'}</i></p>
        </>
      );
    }
    
    

Show more

You can also rewrite using the [ ` async ` / ` await `
](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Statements/async_function) syntax, but you
still need to provide a cleanup function:

App.js

App.js

Reset  [ Fork
](https://codesandbox.io/api/v1/sandboxes/define?undefined&environment=create-
react-app "Open in CodeSandbox")

    
    
    import { useState, useEffect } from 'react';
    import { fetchBio } from './api.js';
    
    export default function Page() {
      const [person, setPerson] = useState('Alice');
      const [bio, setBio] = useState(null);
      useEffect(() => {
        async function startFetching() {
          setBio(null);
          const result = await fetchBio(person);
          if (!ignore) {
            setBio(result);
          }
        }
    
        let ignore = false;
        startFetching();
        return () => {
          ignore = true;
        }
      }, [person]);
    
      return (
        <>
          <select value={person} onChange={e => {
            setPerson(e.target.value);
          }}>
            <option value="Alice">Alice</option>
            <option value="Bob">Bob</option>
            <option value="Taylor">Taylor</option>
          </select>
          <hr />
          <p><i>{bio ?? 'Loading...'}</i></p>
        </>
      );
    }
    
    

Show more

Writing data fetching directly in Effects gets repetitive and makes it
difficult to add optimizations like caching and server rendering later. [ It’s
easier to use a custom Hook—either your own or maintained by the community.
](/learn/reusing-logic-with-custom-hooks#when-to-use-custom-hooks)

#####  Deep Dive

####  What are good alternatives to data fetching in Effects?

Show Details

Writing ` fetch ` calls inside Effects is a [ popular way to fetch data
](https://www.robinwieruch.de/react-hooks-fetch-data/) , especially in fully
client-side apps. This is, however, a very manual approach and it has
significant downsides:

  * **Effects don’t run on the server.** This means that the initial server-rendered HTML will only include a loading state with no data. The client computer will have to download all JavaScript and render your app only to discover that now it needs to load the data. This is not very efficient. 
  * **Fetching directly in Effects makes it easy to create “network waterfalls”.** You render the parent component, it fetches some data, renders the child components, and then they start fetching their data. If the network is not very fast, this is significantly slower than fetching all data in parallel. 
  * **Fetching directly in Effects usually means you don’t preload or cache data.** For example, if the component unmounts and then mounts again, it would have to fetch the data again. 
  * **It’s not very ergonomic.** There’s quite a bit of boilerplate code involved when writing ` fetch ` calls in a way that doesn’t suffer from bugs like [ race conditions. ](https://maxrozen.com/race-conditions-fetching-data-react-with-useeffect)

This list of downsides is not specific to React. It applies to fetching data
on mount with any library. Like with routing, data fetching is not trivial to
do well, so we recommend the following approaches:

  * **If you use a[ framework ](/learn/start-a-new-react-project#production-grade-react-frameworks) , use its built-in data fetching mechanism. ** Modern React frameworks have integrated data fetching mechanisms that are efficient and don’t suffer from the above pitfalls. 
  * **Otherwise, consider using or building a client-side cache.** Popular open source solutions include [ React Query ](https://tanstack.com/query/latest/) , [ useSWR ](https://swr.vercel.app/) , and [ React Router 6.4+. ](https://beta.reactrouter.com/en/main/start/overview) You can build your own solution too, in which case you would use Effects under the hood but also add logic for deduplicatin