I am trying to sort an object in a nested v-for loop before rendering. I have the sorting figured out, and when I log it to the console, I can see that it's working, but when I return the object, chips
, I get a warning:
[Vue warn]: You may have an infinite update loop in a component render function.
If I create a copy of the object, sort it and return chipsCopy
instead, it works just fine, and there is no warning. Cool, but this seems unnecessarily redundant. Is there something I can do so that I don't need to make the copy and not upset Vue's rendering?
The Vue:
<div
v-for="attachment in attachments"
:key="attachment.attachment"
:sort-by="attachment.attachmentDescription">
<div>{{ attachment.attachment }}</div>
<div>{{ attachment.attachmentDescription }}</div>
<div
v-for="(corsp, indx) in alphaOrder(attachment.correspondenceTemplateList)"
:key="`${indx}-${attachment.attachment}-${corsp.categoryCode}-${corsp.letterCode}-${corsp.orgCode}`">
<v-chip
@click="gotoLetter(corsp.letterCode,corsp.orgCode)">
{{ corsp.letterCode }}-{{ corsp.orgCode }}
</v-chip>
</div>
</div>
The JS:
methods: {
alphaOrder(chips) {
// Must create a copy of the object or Vue warns of an infinite loop rendering error.
const chipsCopy = chips.map(c => ({
...c,
}));
function compare(a, b) {
var chipA = a.letterCode "-" a.orgCode;
var chipB = b.letterCode "-" b.orgCode;
if (chipA < chipB){
return -1;
}
if (chipA > chipB){
return 1;
}
return 0;
}
return chipsCopy.sort(compare);
},
},
CodePudding user response:
sort
modifies the array in place. If you don't create a copy of the array first then you'll be mutating local data during the render which is not allowed (hence the infinite update loop warning).
You can just shallow copy the array like this at the end of the method before you sort:
return chips.slice().sort(compare)
It would be better to pre-compute this using a computed property so it doesn't have to recalculate the sorting every time the view updates (computed properties only update when necessary).