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).
This isn't helpful at all (respect), because defining the tree structure upfront in the
state
isn't something real world application do. most of the time you have no idea what the object will have inside of it.Plus defining
nestedObj
structure upfront in thestate
makes it reactive by design and when you don't have that structure in your backyard ready to go, you have to do hacky stuff to get reactivity working.