Reputation: 77
I've always thought that object.assign and spread operator are similar.
But today, I have an error 'You may have an infinite update loop in a component render'
State in advance, the structure of the parent object is like this:
I tried the following three ways:
one: spread operator, got this error 'You may have an infinite update loop in a component render'
const template = { ...parent , path: '', noShowingChildren: true }
this.onlyOneChild = template
two: Deep Copy, got this error 'You may have an infinite update loop in a component render'
const template = JSON.parse(JSON.stringify(parent))
template.path = ''
template.noShowingChildren = true
this.onlyOneChild = template
three: Object.assign, works fine.
const template = Object.assign(parent, { path: '', noShowingChildren: true })
this.onlyOneChild = template
These three situations, the results make me feel very confused.
Can someone answer this question for me?
Here is the code.Thank you for your help.
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
<router-link
v-if="onlyOneChild.meta"
:to="resolvePath(onlyOneChild.path)"
>
<el-menu-item
:index="getIndex(onlyOneChild.path)"
:class="{'submenu-title-noDropdown':!isNest}"
>
<item
v-if="onlyOneChild.meta"
:icon="onlyOneChild.meta.icon||item.meta.icon"
:title="onlyOneChild.meta.title"
/>
</el-menu-item>
</router-link>
</template>
export default {
name: 'SidebarItem',
components: { Item, AppLink },
props: {
// route object
item: {
type: Object,
required: true
},
isNest: {
type: Boolean,
default: false
},
basePath: {
type: String,
default: ''
}
},
data () {
return {
onlyOneChild: null
}
},
methods: {
hasOneShowingChild (children, parent) {
const showingChildren = children.filter(item => {
// console.log(item)
if (item.meta.hidden) {
return false
} else {
// Temp set(will be used if only has one showing child)
this.onlyOneChild = item
return true
}
})
// When there is only one child router, the child router is displayed by default
if (showingChildren.length === 1) {
return true
}
// Show parent if there are no child router to display
if (showingChildren.length === 0) {
console.log('this is parent object:', parent)
// const template = { ...parent , path: '', noShowingChildren: true }
// const template = { ...JSON.parse(JSON.stringify(parent)), path: '', noShowingChildren: true }
// const template = JSON.parse(JSON.stringify(parent))
// template.path = ''
// template.noShowingChildren = true
const template = Object.assign(parent, { path: '', noShowingChildren: true })
this.onlyOneChild = template
return true
}
return false
}
}
}
Upvotes: 0
Views: 138
Reputation:
The first two methods you're using (parsing JSON and spreading) will create new objects or references, while the last method (assign) will use the exact same one and just assign new values to it. So I can only assume that the first two will trigger a state update by changing this.onlyOneChild
completely, which will in return trigger another render, while the last one will not trigger a state change (since it's changing the values on that object and not the entire reference) and not trigger another rerender.
Upvotes: 1