Home > database >  Updating useState array with promise chaining with Axios
Updating useState array with promise chaining with Axios

Time:01-05

I'm currently update useState array with sequential call to backend API with promise chaining using Axios.

I want to sequentially call 3 different API endpoints and gradually add elements so the total number of items in the array is 20.

My code currently looks something like this:

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

function getData() {
  const target = 'http://localhost:5000/api/backend/target/'

  axios.get(target   'one')
  .then(res => {
    setData([...data, ...res.data].slice(0, 20))
  })
  .then(axios.get(target   'two'))
  .then(res => {
    if (data.length < 20) {
      setData([...data, ...res.data].slice(0, 20))
    }
  })
  .then(axios.get(target   'three'))
  .then(res => {
    if (data.length < 20) {
      setData([...data, ...res.data].slice(0, 20))
    }
  })
}

useEffect(() => {
  getData()
}, [])

This works (not really) if the first endpoint returns more than 20 entries, but doesn't work if the first endpoint returns less than 20 entries, which means that the call to other two endpoints are simply not working.

CodePudding user response:

You have two problems. First there's this:

.then(axios.get(target   'two'))

This code immediately calls axios.get(target 'two'), and passes its result into .then. So you're actually doing all the .gets right away, and since .then is expecting a function not a promise, it won't run anything later.

Instead, you need to pass a function into .then, which tells it what you want to eventually do, as in:

.then(() => axios.get(target   'two'))

Secondly, there's this:

if (data.length < 20) {
  setData([...data, ...res.data].slice(0, 20))
}

The data variable here is the empty array from the first render of the component. Any changes you've made to the state since then are not in here, so data.length will always be less than 20, and you'll always be copying an empty array.

Instead, you need to use the function version of setState to make sure you have the latest version of the state:

setData(prev => {
  if (prev.length < 20) {
    return [...prev, ...res.data].slice(0, 20);
  } else {
    return prev;
  }
});
  • Related