Search code examples
javascriptarraysreactjsreact-state-management

Easy way to check if array of objects exists in array of objects before setting state React JS


Consider the following:

  this.setState({
    validations: [...this.state.validations, ...validations]
  }, () => {
    // ... Do something
  });

Where I am doing: [...this.state.validations, ...validations] validations is an an array of objects.

So for example:

// validation
[{message: 'hello', isError: true, fieldId: 87}, ....] 

Essentially every time we have a validation error we set an array of objects to an array as you see above.

The issue is that sometimes duplicate objects get added. By duplicate I mean on the message section, so this.state.validations could look like:

[
  {message: 'hello', isError: true, fieldId: 87}, 
  {message: 'hello', isError: true, fieldId: 87}, 
  {message: 'hello', isError: true, fieldId: 87}, 
  ...
]

What I would like to do is filter this.state.validations based on the message and fieldId in validations and say:

 // If this message doesn't exist for this field id, set it.

Is there a simple non messy way of doing this where I could use filter or something, to loop over the state validations and the validations comparing both fieldId and message and if it doesn't exist: add it?


Solution

  • You can create a Set of "keys" from your existing state validations array where each key is a string of the form message|fieldId. Then you can create your new array by filtering out elements from validations based on whether on not keys of the new validation messages exist in the set created earlier:

    const stateValidations = [
      {message: 'hello', isError: true, fieldId: 87},
      {message: 'world', isError: true, fieldId: 87},
      {message: 'hi', isError: true, fieldId: 88}
    ];
    const validations = [
      {message: 'hello', isError: true, fieldId: 87},
      {message: 'there', isError: true, fieldId: 88}
    ];
    
    const messageKey = ({message, fieldId}) => `${message}|${fieldId}`;
    const existing = new Set(stateValidations.map(messageKey));
    
    const res = [...stateValidations, ...validations.filter(v => !existing.has(messageKey(v)))];
    console.log(res);