Error while sorting array of objects Cannot assign to read only property '2' of object '[object Array]'

JavascriptSorting

Javascript Problem Overview


I'm having array of objects where object looks like this (values change):

   {
     stats: {
        hp: 2,
        mp: 0,
        defence: 4,
        agility: 11,
        speed: 6,
        strength: 31
     }
   }

I want to sort them in descending order by speed doing:

  array.sort((a, b) => {
            return b.stats.speed - a.stats.speed
        })

However I'm getting this error and I can't really decipher whats going on:

TypeError: Cannot assign to read only property '2' of object '[object Array]'

What am I missing?

Edit: Array of object in redux store:

const enemyDefaultState = [
{
    name: 'European Boy1',
    stats: {
        hp: 2,
        mp: 0,
        defence: 4,
        agility: 11,
        speed: 6,
        strength: 31
    }
},
{
    name: 'European Boy2',
    stats: {
        hp: 2,
        mp: 0,
        defence: 4,
        agility: 4,
        speed: 2,
        strength: 31
    }
},
{
    name: 'European Boy3',
    stats: {
        hp: 2,
        mp: 0,
        defence: 4,
        agility: 7,
        speed: 7,
        strength: 31
    }
},

]

I import the array and assign it to the variable:

 let enemies = getState().enemy;
        if (enemies) {
            //sort by speed stat
            enemies.sort((a, b) => {
                return b.stats.speed - a.stats.speed
            })
        }

Javascript Solutions


Solution 1 - Javascript

Because the array is frozen in strict mode, you'll need to copy the array before sorting it:

array = array.slice().sort((a, b) => b.stats.speed - a.stats.speed)

Solution 2 - Javascript

The reason as Patrick stated is because the array is frozen. So any method of copying the array will work such as the one he suggests.

array = array.slice().sort((a, b) => b.stats.speed - a.stats.speed)

I just want to add that the reason the array is frozen in your case is because your using the array as props from the redux store and props in React are immutable hence your not being able to mutate the array.

Solution 3 - Javascript

The array is frozen to prevent mutation of the redux state. You use react cloneElement(): https://reactjs.org/docs/react-api.html#cloneelement

[...enemies].sort((a, b) => {
                return b.stats.speed - a.stats.speed
            })

Solution 4 - Javascript

To be clear, the issue is not purely that the array is frozen. Frozen arrays can be iterated over. As noted in https://stackoverflow.com/questions/49278578/reactjs-sorting-typeerror-0-is-read-only, the issue is that Array.sort sorts the array in-place, meaning it attempts to mutate the array. That's why you need to pass it a mutable copy of the array.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMazMatView Question on Stackoverflow
Solution 1 - JavascriptPatrick RobertsView Answer on Stackoverflow
Solution 2 - JavascriptNick FriedmanView Answer on Stackoverflow
Solution 3 - JavascriptslashView Answer on Stackoverflow
Solution 4 - JavascriptMatthew HerbstView Answer on Stackoverflow