-1

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?

ewef
  • 57
  • 8

1 Answers1

1

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])
Arun Kumar Mohan
  • 11,517
  • 3
  • 23
  • 44
  • @ewef You're welcome. Did you understand why the code in the question didn't work? – Arun Kumar Mohan Apr 05 '21 at 23:52
  • As far as I understand from the answer in the link you sent, my code is executed immediately. Thus, I should have used ```Promise``` to contain the immediate objects. In my code, instead of using ```Promise```, I pushed objects to array. Am I understanding correctly? – ewef Apr 05 '21 at 23:57
  • @ewef "my code is executed immediately." Exactly. "Thus, I should have used Promise to contain the immediate objects." Not sure if I understand this part. The response is only available when the promise resolves and you cannot access it outside the async function. Does that make sense? – Arun Kumar Mohan Apr 05 '21 at 23:59
  • I really appreciate your thoughtful explanation. I have never thought of ```Promise```. – ewef Apr 06 '21 at 00:00