0

I am using a computed value that returns an array. This computed value is being used in a Vue component.

<component v-for="(item, index) in sortedItems" ...more props />

The prop that I'm using to use in the computed value comes in the form of

const props = defineProps({ items: { type: Array, default: () => [] } })

The computed assignment

const sortedItems = computed(() => {
    return props.items.sort((l, r) => {
        const lValues = l.item.subItems.map(i => i.optValue)
        const rValues = r.item.subItems.map(i => i.optValue)
        const lMin = (Math.min.apply(null, lValues));
        const rMin = (Math.min.apply(null, rValues));
        return (lMin < rMin ? -1 : 1);
    })
});

Apologies for the length, but here is a representation of the data structure coming from the prop.

[
    {
        item: {
            name: "item1",
            subItems: [
                {
                    optName: "name1",
                    optValue: 60
                },
                {
                    optName: "name2",
                    optValue: 70
                },
            ]
        },
    },
    {
        item: {
            name: "item2",
            subItems: [
                {
                    optName: "name3",
                    optValue: 80
                },
                {
                    optName: "name4",
                    optValue: 90
                },
            ]
        },
    },
    {
        item: {
            name: "item3",
            subItems: [
                {
                    optName: "name5",
                    optValue: 50
                },
                {
                    optName: "name6",
                    optValue: 60
                },
            ]
        },
    },
]

I have run the sort on the dataset in a test environment outside of vue/computed/props and it works great. I am missing something when it comes to Vue. I thought maybe caching or holding previous version, but I keep coming up blank. ANy help/guidance would be greatly appreciated.

2
  • perhaps whatever is using your component isn't passing the expected data in as a prop - what happens if you <component v-for="(item, index) in items" ...more props /> Commented Jun 21 at 3:05
  • So the component renders, and the initial implementation was simply passing the prop to the component. Implementing the sort is resulting in the exact same order, which is why I think I'm missing something about props and mutability. I have even stepped through with breakpoints into the sort function and it goes through the motions, just when it comes to render time, it's like the sort never happened.
    – Maldaer
    Commented Jun 21 at 3:09

1 Answer 1

2

Vue's props for objects/arrays are references and not copies, what is happening here is that your computed is modifiying the passed prop, which is something which should definitely be avoided.

Why does it modify the passed prop?

Because of Array.prototype.sort(), which sorts the array in place, so both your computed value and your original one will be sorted. To not have it sort in place just copy the array, return [...props.items].sort(() => {}).

Here is a playground version of what you want to achieve (I think).

1
  • That worked like a champ, thank you!
    – Maldaer
    Commented Jun 21 at 13:03

Not the answer you're looking for? Browse other questions tagged or ask your own question.