100

I have a function that needs to extend a javascript array, including a new attribute called selected:

export const initSelect = (data) => {

    let newData = data.concat();
    newData.map((item) => {
        item.selected = false;
    })

    return newData;
}

data is a ReactJS state value (comes from this.state.data when calling the function), but this didn't seem to be a problem as newData is a new copy of data array...

I'm getting the following error:

TypeError: Cannot add property selected, object is not extensible
1

4 Answers 4

142

You probably need to copy the objects:

export const initSelect = (data) => {
 return data.map((item) => ({
     ...item,
     selected: false       
 }));
}
Sign up to request clarification or add additional context in comments.

3 Comments

@Jonasw the op is misusing concat and map. I think your solution should not be misusing them also.
Will the returned object a copy of data ? I will use the return to set the ReactJS object state....
Works!!!! I did not get this error locally but in the deployed version of my app, anyone here knows why this is happening ?
52

You can not extend item with selected property, and your array is just a shallow copy.

If you want to be able to extend, you will have to do a deep copy of your array. It may be enough with:

let newData = data.map((item) => 
    Object.assign({}, item, {selected:false})
)

3 Comments

I see the same error with Object.assign approach. I manage to solve it using @Jonas anwer.
Then probably you are doing something wrong @RocíoGarcíaLuque, as Jonas' solution and mine are equivalent according to my understandings of stackoverflow.com/a/50558264/2832398
You are totally right. I cannot remember the situation, but probably yes, I was doing something wrong. Your solution is perfectly valid :+1:
23
data = JSON.parse(JSON.stringify(data));

As of 2024 use: structuredClone(value, options)

https://developer.mozilla.org/en-US/docs/Web/API/Window/structuredClone

3 Comments

That seems like some unnecessary "stringifycation". There could also be objects in data that could not be stringified and therefor destroy the original data.
for my "unpushable" array, this was perfect
you can rely on lodash.deepClone(data) to avoid nested data loss
14
const newObj = Object.assign({selected: false}, data);

2 Comments

While this code snippet may solve the question, including an explanation really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion.
Please, keep in mind that this code afaik is not equivalent. If data already contains selected: true for example, the new object will end up with selected: true.

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.