I want to make a search component that receives an object and then filters it by user input. Then pass it again to parent to show what i filtered. (Nuxt)
// Parent component
<AppSearch :bookmarks="bookmarks" />
...
bookmarks = [ { "title": "Facebook", "url": "https://facebook.com" }, { "title": "Google", "url": "https://google.com/" } ]
// Child search component
<template>
<input type="text" v-model="searchQuery"> </input>
</template>
<script>
export default {
props: ['bookmarks'],
data() {
return {
searchQuery: null,
}
},
computed: {
filteringBookmarks:{
get: function() {
if(this.searchQuery){
return this.bookmarks.filter(data => data.title.toLowerCase().includes(this.searchQuery.toLowerCase()))
} else{
return this.bookmarks;
}
}
}
},
watch: {
filteringBookmarks(newValue) {
console.log(`yes, computed property changed: ${newValue}`); // <--- INFINITES MESSAGES
this.$emit('update:bookmarks', filteringBookmarks)
}
},
}
</script>
I've tried another ways but always ends in the same spot, whole website freezing. Its seems like never stop refreshing "bookmarks". Maybe is a circular problem?
CodePudding user response:
The best way to avoid this circular issue is to watch the searchQuery
<script>
export default {
props: ['bookmarks'],
data() {
return {
searchQuery: null,
}
},
watch: {
searchQuery(newValue) {
let filteringBookmarks=[]
if(newValue){
filteringBookmarks=this.bookmarks.filter(data => data.title.toLowerCase().includes(this.searchQuery.toLowerCase()))
}else{
filteringBookmarks=this.bookmarks;
}
this.$emit('update:bookmarks', filteringBookmarks)
}
},
}
</script>
CodePudding user response:
You are emitting a computed value to the parent component, and the parent updates the bookmarks and pass it as a prop to the child component which makes the computed property to be updated and since you have a watcher on the computed property, it will again emits it's new value causing an infinite loop.
A solution can be to emit search query itself and then filter the results on the parent element.
