Vue.js provides a good example for working with deep nested objects or tree data structures. But, how about when Vuex is involved?
Fortunately, Evan You (Vue.js' creator) gives us a hint:
...Or, you can use the same flat structure and use ids to reference nested items, and use a Vuex getter in each tree item component to retrieve its children.
So, how do we go about doing that? After a few attempts getting nested objects' reactivity to work, here is what I did.
Let's say we have our nested objects that looks like this in Vuex:
const store = new Vuex.Store({
state: {
nestedObj: [
{ id: 1, parent_id: null, content: 'Hello' },
{ id: 2, parent_id: 1, content: 'World' },
{ id: 3, parent_id: 2, content: 'Welcome!' },
{ id: 4, parent_id: null, content: 'Cool.' },
{ id: 5, parent_id: 2, content: 'Back!' },
]
},
...
})Then, in our getters:
getters: {
getChildrenByID: ({ nestedObj }) => (id) => {
return nestedObj.filter( obj => obj.parent_id == id );
},
getParent({ nestedObj }) {
return nestedObj.filter( obj => obj.parent_id == null );
}
},
...
})Next, in our Child.vue component:
<template>
<div class="box">
<p>
{{ data.body }}
</p>
<!-- Child -->
<child v-for="(item, index) in getChildrenByID(data.id)"
:key="item.id"
:data="item">
</child>
</div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
props: ['data'],
computed: {
...mapGetters([
'getChildrenByID',
]),
},
}
</script>Finally, in our Parent.vue component:
<template>
<div class="section">
<child v-for="(child, index) in getParent"
:key="child.id"
:data="child">
</child>
</div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
computed: {
...mapGetters([
'getParent',
]),
},
}So now, when we do nestedObj.push({ id: 6, parent_id: 5, content: 'New content!!' }) in our Vuex's mutation, the nested object view will be updated accordingly (reactive).
@jhkueh This is exactly what I needed :) tnx
Only thing is, in my case i need
nestedObj update -> { id: 5, parent_id: 2, content: 'Back! UPDATED' },
to accualy trigger mapped getter in child component, but it doesn't, or im doing something wrong :/