2

I tested this a few times and I can't figure out why useState will reload, in all the tutorials and guides online, setState if the value is the same it should not cause a component re-render

My code is like this:

const [order, setOrder] = useState([]);
setOrder([500, 400, 400, 450]);
setOrder([500, 400, 400, 450]); //this causes react to rerender although the items and sequence are the same

I don't want it to re-render because each time the "order" array is changed, an API call is being made, but I only want it to call the API if the values or sequences are actually different

I tried disabling and enabling react StrictMode, and but it still rerender. I don't know why other people video it does not seem to rerender

CodeThing
  • 2,580
  • 2
  • 12
  • 25

1 Answers1

3

It's rerendering because the new value is not equal to the previous value. It's a new array. useState compares values by identity but you can compare by any definition of equality you wish in your code.

In this case shallow element equality would make sense.

function elementsEqual(a, b) {
  return a.length === b.length && a.every((_, index) => a[index] === b[index]);
}

Then in your callbacks instead of passing in the new value as is setOrder(newOrder), pass a function that returns the old value if it's equal to the new otherwise the new value.

setOrder(prevValue => elementsEqual(prevValue, newOrder) ? prevValue : newOrder);

Now your component will only rerender when the elements of order change.

Jemi Salo
  • 3,401
  • 3
  • 14
  • 25
  • This does not work setOrder(prevValue => elementsEqual(prevValue, obj[0].departments["sales"].map(f=> f.userId)) ? prevValue : obj[0].departments["sales"].map(f=> f.userId)); – wynnawinner Apr 06 '23 at 10:51
  • It still refreshes every single time even though obj is constant – wynnawinner Apr 06 '23 at 10:51
  • I cannot help you with problems you haven't provided information about. Sounds like your code has additional problems on top of what you described in this question. – Jemi Salo Apr 08 '23 at 12:05