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
}
}
}
JSON.parse(JSON.stringify(parent))
is never a good idea. There are much better ways to copy an object. - T.J. CrowderObject.assign
code is not the same as your spread code, you're updating the existingparent
object in theObject.assign
code but creating an entirely new object in the spread code. The equivalentObject.assign
code would beconst template = Object.assign({}, parent, { path: '', noShowingChildren: true })
. Since with yourassign
you're not creating a new object, it's probably just hiding the actual problem. (I haven't done Angular in years, so I can't point to what the actual issue is.) - T.J. Crowderconst template = Object.assign({}, parent, { path: '', noShowingChildren: true })
, indeed, the problem is not a deep copy of the problem, thank you for your help - J.Kuai