2

I have a function that is supposed to add unique elements to an array:

addLanguage = (val) => {

    for(let i=0; i< val.length; i++){
        console.log(val[i].id)
        if(this.state.createNewDeliveryData.languages.indexOf(val[i].id === -1)){
             this.state.createNewDeliveryData.languages.push(val[i])
        }
    }
}

the argument 'val' each time gets an array with appended elements (I have a multi select box on UI from where I add languages), that's why in If loop I am trying to check if my languages array already has that specific element. However this has no effect and at the end my languages array contains same elements i.e. same element is added twice or thrice etc. on subsequent calls.

['German']
['German', 'German', 'Arabic']
...

What am I doing wrong?

2
  • You have to check manually by any unique identifier of object is it exist into array or not before push then you can push. for this you can use lodash uniq or unionWith. Commented Jul 11, 2017 at 8:41
  • Where's id coming from? Looks like an array of strings to me. Commented Jul 13, 2022 at 16:15

3 Answers 3

3

You are looking for the index of false in your array. That's because, indexOf(val[i].id === -1) will always check indexOf(false) which is -1. So you re-add each language.

You are probably after an algorithm more similar to this:

addLanguage = (val) => {
    // Get a copy of the languages state. 
    const languages = [...this.state.createNewDeliveryData.languages];
    for(let i=0; i< val.length; i++){
        if(languages.indexOf(val[i].id) === -1) { // notice that there is a parenthesis after `id`.
            languages.push(val[i].id)
        }
    }
    this.setState({createNewDeliveryData: {languages}}); // update state and trigger re-render if there are new languages. 
}

Note that you should always use setState to mutate the state in react.

Sign up to request clarification or add additional context in comments.

2 Comments

Isn't that the correct way to check for element existence before pushing to array?
No. In your code you litterally do if(array.indexOf(false)===-1. when you don't want to store booleans in your array
2

Instead of checking each element in a loop, you could just use Set object to remove every duplicated element.

Note: I assume that the val variable is an array.

addLanguage = (val) => [...new Set(val)];

Comments

2

You have a few issues with your code:

  • First of all, never, ever mutate this.state directly. It is anti-pattern and may yield undesired results. Use this.setState() instead.

  • There is no need to do indexOf in a loop. indexOf will iterate the array and return the index of the searched item, or -1 if it was not in the array.

  • You have to create a copy for the this.state.createNewDeliveryData object and for the languages array.


That said, one solution could be:

addLanguage = (val) => {
  if(this.state.createNewDeliveryData.languages.indexOf(val) === -1) {
    let obj = Object.assign({}, this.state.createNewDeliveryData);  //shallow-copy object
    let arr = obj.languages.slice();  //copy array
    arr.push(val);  //push the value
    obj.languages = arr;  //assign the new array to our copied object
    this.setState({createNewDeliveryData: obj});  //replace the old object with the new
  }
}

or in a more compact form:

addLanguage = (val) => {
  if(this.state.createNewDeliveryData.languages.indexOf(val) === -1) {
    let obj = Object.assign({}, this.state.createNewDeliveryData);  //shallow-copy object
    obj.languages = obj.languages.slice().push(val);
    this.setState({createNewDeliveryData: obj});  //replace the old object with the new
  }
}

6 Comments

First of all thanks! I actually do not want to push 'val' as it is, that's why I was iterating over the val array and using val[i].id to push into my languages array.
Also, if I put a console.log(this.state.createNewDeliveryData.languages) outside if loop, it prints empty array each time
@Nitish, yes my bad. It should be === -1, not > -1. Corrected the error.
this latest update is throwing : Failed prop type: Invalid prop value of type array supplied to Value, expected object
Okay! Answer from Christopher worked, so I accepted it. Sorry I can not accept two answers but I have given +1. Thanks a lot anyway :)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.