Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Vue 3 debugging reference for reactivity issues, computed errors, watcher bugs, async failures, and SSR hydration problems.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
reference/v-for-computed-reverse-sort.md
1---2title: Copy Arrays Before reverse() or sort() in Computed Properties3impact: MEDIUM4impactDescription: reverse() and sort() mutate the original array, causing unintended side effects in computed getters5type: gotcha6tags: [vue3, v-for, computed, array, mutation, list-rendering]7---89# Copy Arrays Before reverse() or sort() in Computed Properties1011**Impact: MEDIUM** - The `reverse()` and `sort()` methods mutate the original array in-place. When used directly in a computed property getter, this causes the source array to be modified, leading to infinite reactivity loops or incorrect data state.1213Computed properties should be pure - they calculate a value without side effects. Mutating the source data inside a computed getter violates this principle and causes unpredictable behavior.1415## Task Checklist1617- [ ] Always create a copy of the array before calling `reverse()` or `sort()` in computed properties18- [ ] Use spread operator `[...array]` or `Array.from(array)` or `array.slice()` to copy19- [ ] This applies to any in-place mutation method used in computed getters20- [ ] Consider using `toSorted()` and `toReversed()` (ES2023) which return new arrays2122**Incorrect:**23```javascript24const numbers = ref([1, 2, 3, 4, 5])2526// WRONG: Mutates the original array27const reversedNumbers = computed(() => {28return numbers.value.reverse() // Modifies numbers.value!29})3031// WRONG: Same issue with sort32const sortedItems = computed(() => {33return items.value.sort((a, b) => a.name.localeCompare(b.name))34})35```3637**Correct:**38```javascript39const numbers = ref([1, 2, 3, 4, 5])4041// CORRECT: Create a copy first with spread operator42const reversedNumbers = computed(() => {43return [...numbers.value].reverse()44})4546// CORRECT: Create a copy before sorting47const sortedItems = computed(() => {48return [...items.value].sort((a, b) => a.name.localeCompare(b.name))49})5051// CORRECT: Using slice() to copy52const reversedNumbers = computed(() => {53return numbers.value.slice().reverse()54})5556// CORRECT: ES2023 non-mutating methods (if supported)57const reversedNumbers = computed(() => {58return numbers.value.toReversed()59})6061const sortedItems = computed(() => {62return items.value.toSorted((a, b) => a.price - b.price)63})64```6566## Also Applies to Methods Used in Templates6768When using methods to filter/sort in nested v-for loops, the same rule applies:6970```javascript71// CORRECT: Method that doesn't mutate72function getSortedChildren(parent) {73return [...parent.children].sort((a, b) => a.order - b.order)74}75```7677```html78<ul v-for="parent in parents" :key="parent.id">79<li v-for="child in getSortedChildren(parent)" :key="child.id">80{{ child.name }}81</li>82</ul>83```8485## Reference86- [Vue.js List Rendering - Displaying Filtered/Sorted Results](https://vuejs.org/guide/essentials/list.html#displaying-filtered-sorted-results)87