0

how to avoid re-render when i have more than one setState in useEffect ?

i want to make 2 API calls and set 3 different states in useEffect ( when component did mount ) and only one re-render

something like this

useEffect(()=>{
   axios.get('http://localhost:81/api/myapi/')
   .then(res=>{
     setName(res.data['name']);
     setPrice(res.data['price']);
   })

   axios.get('http://localhost:81/api/mysecondapi/')
   .then(res=>{
     setColors(res.data['colors']);
   })
 },[]);

i want only one render after all the sets. i know it's correct to a re-render after every setStates, but how can i make this to do only one ? is it good to put all states in an object ? like class state ?

samir
  • 159
  • 5
  • 13
  • 1
    Yes, you can put all state in an object and use useReducer instead of useState. – Janiis Jul 11 '19 at 13:12
  • 1
    You can refer to - https://stackoverflow.com/questions/53574614/multiple-calls-to-state-updater-from-usestate-in-component-causes-multiple-re-re . seems like same problem – Monika Mangal Jul 11 '19 at 13:15

2 Answers2

3

If you don't want to use useReducer, could could use Promise.all with your fetches

useEffect(()=>{
   const stateData = {}
   const fetch1 = axios.get('http://localhost:81/api/myapi/')
   const fetch2 = axios.get('http://localhost:81/api/mysecondapi/')
   Promise.all([fetch1, fetch2]).then(([res1,res2])=>{
     setName(res1.data['name']);
     setPrice(res1.data['price']);
     setColors(res2.data['colors']);
   })
 },[]);

This will cause 3x re-renders, but that isn't the same as 3x DOM updates.

If you only want a single re-render, combine all your updates into one object:

Promise.all([fetch1, fetch2]).then(([res1, res2]) => {
  setNamePriceColor({ name: res1.data['name'],
    price: res1.data['price'],
    colors: res2.data['colors'] })
})
Will Jenkins
  • 9,507
  • 1
  • 27
  • 46
1

You should try chaining promises

useEffect(()=> {
   axios.get('http://localhost:81/api/myapi/')
   .then(res => {
     setName(res.data['name']);
     setPrice(res.data['price']);
   })
   .then(() => axios.get('http://localhost:81/api/mysecondapi/'))
   .then(res => {
     setColors(res.data['colors']);
   })

 },[]);

If you have to separeted axios call, react won't be able to batch the state update.

Vencovsky
  • 28,550
  • 17
  • 109
  • 176