Skip to content Skip to sidebar Skip to footer

React Useeffect() : Most Efficient Way To Compare If Two Arrays Of Objects Are Equal

I have a useEffect() that should trigger when an array of objects changes. useEffect(() => { setNotesToRender(props.notes) }, [props.notes]); The useEffect dependency c

Solution 1:

First of all 1k objects is not a large number of objects, but getting back to the question: the easiest way is to use

JSON.stringify(object1) === JSON.stringify(object2);

But it is not the most efficient, when performance is an issue, the smartest thing I could think of is to use a meta property like version and whenever we update the object in any way we increment the version as well. Then all you have to do is to check two arrays based on id + version mapping.

If the second option is not desired you could use lodash.deepCompare or create your own function, takea look at How to make data input readonly, but showing calendar? and simply check object by object while iterating.

Solution 2:

True, useEffect cannot compare array of objects so let the useEffect hook runs.

But what you can do is to add an if-statement whether JSON.stringified notesToRender and JSON.stringified props.notes are equal.(Or you can use lodash/isEqual) to prevent the set state method running.

However, if you think that is still not an efficient solution, we will have to see why do you need useEffect in the first place.

From your code, I think you are setting a useState hook based on the incoming props.

Thinking about that again, why would you not consider to directly render the props instead.

From official React doc page : https://reactjs.org/docs/thinking-in-react.html#step-3-identify-the-minimal-but-complete-representation-of-ui-state

  1. Is it passed in from a parent via props? If so, it probably isn’t state.
  2. Does it remain unchanged over time? If so, it probably isn’t state.
  3. Can you compute it based on any other state or props in your component? If so, it isn’t state.

Solution 3:

What is the most efficient way

The most efficient way is likely a custom compare for this particular shape of data. You could use JSON.stringify or some other generic comparing function, but it's not likely to be the most efficient for obvious reasons.

So in your example a simple compare function might look like ->

const array1 = [{id:1,title:'one'},{id:2,title:'two'},{id:3,title:'three'}];
const array2 = [{id:1,title:'one'},{id:2,title:'two'},{id:3,title:'four'}];

constarrayIsEqual = (a1, a2) => 
  a1 === a2 ||
  a1.length === a2.length &&
  a1.every((f,i) => 
    f.id === a2[i].id &&
    f.title === a2[i].title
  )
  
  
//testsconst a1clone = [...array1];

//different arrays not equalconsole.log(arrayIsEqual(array1, array2)); //false//different arrays equalconsole.log(arrayIsEqual(array1, a1clone)); //true//different arrays same values, but different order
a1clone.reverse();
console.log(arrayIsEqual(array1, a1clone)); //false//same arrays, fastest checkconsole.log(arrayIsEqual(array1, array1)); //true

Post a Comment for "React Useeffect() : Most Efficient Way To Compare If Two Arrays Of Objects Are Equal"