Monday, June 3, 2024
 Popular · Latest · Hot · Upcoming
48
rated 0 times [  54] [ 6]  / answers: 1 / hits: 108942  / 6 Years ago, fri, november 9, 2018, 12:00:00

Basically we do API calls in componentDidMount() life cycle method in React class components like below



     componentDidMount(){
//Here we do API call and do setState accordingly
}


But after hooks are introduced in React v16.7.0, its all like functional components mostly



My query is, where exactly do we need to make API call in functional component with hooks?



Do we have any method for it similar like componentDidMount()?


More From » reactjs

 Answers
146

2023 Update: Load data on the server or use React Query


The newly-written official docs provides an example of how to fetch data with useEffect without race condition issues.


If you're using a metaframework like Next.js or Remix, they allow for data fetching on the server and passing the data to the components as props, which can eliminate the need for fetching data on the client. This tends to be better for UX and performance due elimination of the traditional fetch-after-you-render model, or prefetching data needed for the next page in the case of transitions.


If you want a pure client-side solutions which work well with Suspense:



  • React Query is the most popular declarative data fetching library for React that provides useful features like caching, refetching, prefetching, etc.

  • SWR is a more lightweight option.




2021 Update: Suspense


As Dan Abramov said on this GitHub Issue:



Longer term we'll discourage this (useEffect) 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





Yes, there's a similar (but not the same!) substitute for componentDidMount with hooks, and it's the useEffect hook.


The other answers don't really answer your question about where you can make API calls. You can make API calls by using useEffect and passing in an empty array or object as the second argument as a replacement for componentDidMount(). The key here is the second argument. If you don't provide an empty array or object as the second argument, the API call will be called on every render, and it effectively becomes a componentDidUpdate.


As mentioned in the docs:



Passing in an empty array [] of inputs tells React that your effect doesn’t depend on any values from the component, so that effect would run only on mount and clean up on unmount; it won’t run on updates.



Here are some examples for scenarios where you will need to make API calls:


API Call Strictly on Mount


Try running the code below and see the result.




function User() {
const [firstName, setFirstName] = React.useState(null);
const [lastName, setLastName] = React.useState(null);

React.useEffect(() => {
fetch('https://randomuser.me/api/')
.then(results => results.json())
.then(data => {
const {name} = data.results[0];
setFirstName(name.first);
setLastName(name.last);
});
}, []); // <-- Have to pass in [] here!

return (
<div>
Name: {!firstName || !lastName ? 'Loading...' : `${firstName} ${lastName}`}
</div>
);
}

ReactDOM.render(<User />, document.querySelector('#app'));

<script src=https://unpkg.com/[email protected]/umd/react.development.js></script>
<script src=https://unpkg.com/[email protected]/umd/react-dom.development.js></script>

<div id=app></div>




API Call Whenever Some Prop/State Changes


If you are for example displaying a profile page of a user where each page has a userID state/prop, you should pass in that ID as a value into the second parameter of useEffect so that the data will be refetched for a new user ID. componentDidMount is insufficient here as the component might not need remounting if you go directly from user A to user B's profile.


In the traditional classes way, you would do:


componentDidMount() {
this.fetchData();
}

componentDidUpdate(prevProps, prevState) {
if (prevState.id !== this.state.id) {
this.fetchData();
}
}

With hooks, that would be:


useEffect(() => {
this.fetchData();
}, [id]);

Try running the code below and see the result. Change the id to 2 for instance to see that useEffect is run again.




function Todo() {
const [todo, setTodo] = React.useState(null);
const [id, setId] = React.useState(1);

React.useEffect(() => {
if (id == null || id === '') {
return;
}

fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)
.then(results => results.json())
.then(data => {
setTodo(data);
});
}, [id]); // useEffect will trigger whenever id is different.

return (
<div>
<input value={id} onChange={e => setId(e.target.value)}/>
<br/>
<pre>{JSON.stringify(todo, null, 2)}</pre>
</div>
);
}

ReactDOM.render(<Todo />, document.querySelector('#app'));

<script src=https://unpkg.com/[email protected]/umd/react.development.js></script>
<script src=https://unpkg.com/[email protected]/umd/react-dom.development.js></script>

<div id=app></div>




You should read up on useEffect so that you know what you can/cannot do with it.


[#53144] Monday, November 5, 2018, 6 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
jaydenathaliam

Total Points: 676
Total Questions: 102
Total Answers: 103

Location: San Marino
Member since Thu, Jun 30, 2022
2 Years ago
;