Fetching data from URL with different id in React Hooks

I am new to React.

The for loop is used to fetch data from the url with different ids.

The object from data contains same keys and different values.

What I want to do is I want to store these data objects into array with index.

Looking like the following:

dataArr [
 0: {key: 1, value: 1},
 1: {key: 2, value: 2},
 2: {key: 3, value: 3}
]

Here is what I have tried.

var ids = [1,2,3]
const [data, setData] = useSate({});
const dataArr = [];
const fetchData = async() => {
  for(var i =0; i < ids.length; i++) {
    axios.get(`http://myURL/${ids[i]}`)
    .then(res => {
       dataArr.push(setData(res.data))
     })
   }
}


useEffect(() => {
   fetchData ();
},[]);
console.log(dataArr[0]) //undefined
console.log(dataArr) // empty
console.log(data) // get objects independently 

Can anybody advise me?

Answer

axios.get is asynchronous and the console.log statements get executed before the promises resolve. I would recommend reading this answer to gain a better understanding.

You can create an array of promises and await them using await Promise.all(...) to fetch all the responses and then call setData with the new state. You should also set the initial state to an empty array.

const [data, setData] = useState([])

useEffect(() => {
  const fetchData = async () => {
    const ids = [1, 2, 3]
    const responses = await Promise.all(
      ids.map((id) => axios.get(`http://myURL/${id}`))
    )
    setData(responses.map((res) => res.data))
  }

  fetchData()
}, [])

If you set up eslint-plugin-react-hooks, it would display a warning to add setData to the dependency array since the effect depends on it. It’s totally fine to add it since the function’s reference won’t change on re-renders.

useEffect(() => {
  const fetchData = async () => {
    const ids = [1, 2, 3]
    const responses = await Promise.all(
      ids.map((id) => axios.get(`http://myURL/${id}`))
    )
    setData(responses.map((res) => res.data))
  }

  fetchData()
}, [setData])