-1

I am using React framework and passing a prop to a component that maintains a state. The prop and state are arrays of objects, and I want to verify whether or not there is any change between the two at some point in my code.

  somethingHasChanged = () => {
    return !isEqual(this.props.array1.sort(), this.state.array1.sort());
  };

Where the objects in the array are defined like so:

    array1: PropTypes.arrayOf(
      PropTypes.shape({
        id: PropTypes.string,
        name: PropTypes.string,
        label: PropTypes.string,
      }),
    ),

The id can be repeated in several objects in the array, so it does not uniquely identify one object. Name and label are optional keys in the json object but it doesn't have to be specified.

Right now I sort both arrays and then check if they are equal, but I'm seeing some weird behavior. Sometimes when I expect both arrays to be equal, they are different because the content is the same but the ordering is not the same even though I call sort() on both. Is there a better, easier/more flexible approach rather than doing a deep comparison?

ronapple14
  • 93
  • 2
  • 10
  • 1
    How do you think it'll sort them w/o a comparison function? Did you try searching the web for "js compare array of objects" since you'll need a custom comparison anyway? There are multiple ways this can be done; you'd likely need to choose one based on your specific requirements, libraries/modules you're already using, etc. – Dave Newton Apr 28 '20 at 17:56
  • Will also need to see what you are doing in `isEqual`. The sort is not working as you expect it to behave, because the sort function does not understand which object is bigger or smaller. – user120242 Apr 28 '20 at 17:56
  • @user120242 isEqual is coming from lodash library. However i do have a question. Why would the sorting change between my prop array and state array if the content is the same? I would expect the same result at the end of calling `sort()` then. It makes sense to me if one array has something different than the other, but in this case (at least from what I know), both arrays are the same – ronapple14 Apr 28 '20 at 18:00
  • I'd check to see if your state has been modified after it was copied from the prop and how. Probably want to actually console.log out the values and compare them. – user120242 Apr 28 '20 at 19:06

1 Answers1

0

Using plain JS something like this

a = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal"},  { value:"a63a6f77-c637-454e-abf2-dfb9b543af6c", display:"Ryan"}]
b = [{ value:"4a55eff3-1e0d-4a81-9105-3ddd7521d642", display:"Jamsheer", $$hashKey:"008"}, { value:"644838b3-604d-4899-8b78-09e4799f586f", display:"Muhammed", $$hashKey:"009"}, { value:"b6ee537a-375c-45bd-b9d4-4dd84a75041d", display:"Ravi", $$hashKey:"00A"}, { value:"e97339e1-939d-47ab-974c-1b68c9cfb536", display:"Ajmal", $$hashKey:"00B"}]

function comparer(otherArray){
  return function(current){
    return otherArray.filter(function(other){
      return other.value == current.value && other.display == current.display
    }).length == 0;
  }
}

var onlyInA = a.filter(comparer(b));
var onlyInB = b.filter(comparer(a));

result = onlyInA.concat(onlyInB);

console.log(result);
Harmenx
  • 938
  • 1
  • 5
  • 13