React state is immutable. You do not want to mutate the state variable directly by pushing to the array. Instead, you want to use your setState function that will update your data state variable.
Understanding useEffect
When you pass a second arguement to the useEffect, in this case data it will update every time the data variable changes causing an infinite loop since every call will update the state.
You can trigger this API request on mount by not passing anything to the useEffect. And then cleanup the API request to prevent possible memory leaks.
Refactor: Pass 1
Cleaning up the useEffect and adding a key attribute to your returned JSX in the map (otherwise you get a warning in the console saying you need to provide a key).
import React, { useEffect, useState } from 'react'
function App() {
const [ data, setData ] = useState([]);
useEffect(() => {
axios
.get('https://jsonplaceholder.typicode.com/users')
.then((res) => {
setData(res.data)
})
.catch((err) => console.log(err));
},[]);
return (
<div className="App">
{data.map((item) => {
return <div key={item.name}>{item.name}</div>; //you want to use a unique key, name may not be unique so use something unique here
})}
</div>
);
}
That should work fine. There is still room for improvement.
Refactor: Pass 2
We want to prevent potential memory leaks in our application so we should add a cleanup to that useEffect. A cleanup tells the useEffect what to do when the component is unmounting. Here, we want to end the API request or cancel it if we unmount before it is finished otherwise it will finish and try to update a state variable that no longer exists.
import React, { useEffect, useState } from 'react'
function App() {
const [ data, setData ] = useState([]);
useEffect(() => {
const axiosSource = axios.CancelToken.source()
const fetchUsers = async () => {
try {
await axios.get(url, { cancelToken: axiosSource.token })
// update state
} catch(error){ //handle error }
}
fetchUser();
return () => {
axiosSource.cancel()
}
},[]);
return (
<div className="App">
{data.map((item) => {
return <div key={item.name}>{item.name}</div>;
})}
</div>
);
}