Vuex state and getters

With vuex is there a reason why it's better to access state directly than via a getter if the getter is just returning the state?
Let us first take care to illustrate this issue:
the store
const store = new Vuex.Store({
state: {
messages: [
{ from: "Bob", to: "Alice", content: "Hello, Alice!" },
{ from: "Alice", to: "Bob", content: "Hi, Bob!" },
{
from: "Bob",
to: "Alice",
content:
`What is the difference between accessing the state directly
rathen than using a getter?`
},
{
from: "Alice",
to: "Bob",
content: `This is your last chance.
After this, there is no turning back.
You take the blue pill—the story ends,
you wake up in your bed and believe whatever you want to believe.
You take the red pill—you stay in Wonderland,
and I show you how deep the rabbit hole goes.
Remember: all I'm offering is the truth. Nothing more.`
}
]
},
getters: {
messages: state => state.messages
}
});
two very different components
In both components, messages are the responsibility of a Vuex store.
RedPill: direct access to the state
export default {
name: "HelloWorld",
computed: {
messages() {
return this.$store.state.messages;
}
}
};
In the component <RedPill />
, we access the state directly via the store object which is injected to all root child components.
The component retrieves the list of messages and can display their content:
<template>
<div class="hello">
<h1>Dependant of the state organization</h1>
<ul v-for="(message, index) in messages" :key="index">
<li>{{message.from}} to {{message.to}}: {{message.content}}</li>
</ul>
</div>
</template>
BluePill: using a getter
export default {
name: "HelloWorld",
computed: {
messages() {
return this.$store.getters.messages;
}
}
};
In the other component `<BluePill />, we access the state via a getter which is not complex since it returns directly the object: const messages = state => state.messages
.
From a component and the application point of view, there is no difference.
how deep does the rabbit hole go?
The RedPill
is dependant of the internal state organization. Every time the state is reorganized, the RedPill
should be updated. The RedPill
has a big responsibility: to know where it can find the list of messages.
On the other hand, the BluePill
is independent of the internal organization of the state because it asks the store, whenever it needs it, to return the list of messages. The BluePill
does not have the responsibility to know where it can find the list of messages.
Let's say that the Vuex store is redesigned to allow organization in modules.
const store = new Vuex.Store({
state: {
messages: [
{ from: "Bob", to: "Alice", content: "Hello, Alice!" },
{ from: "Alice", to: "Bob", content: "Hi, Bob!" },
{
from: "Bob",
to: "Alice",
content:
`What is the difference between accessing the state directly
rathen than using a getter?`
},
{
from: "Alice",
to: "Bob",
content: `This is your last chance.
After this, there is no turning back.
You take the blue pill—the story ends,
you wake up in your bed and believe whatever you want to believe.
You take the red pill—you stay in Wonderland,
and I show you how deep the rabbit hole goes.
Remember: all I'm offering is the truth. Nothing more.`
}
]
},
getters: {
messages: state => state.messages
}
});
Now we want to use Vuex modules:
const store = new Vuex.Store({
modules: {
messages: {
state: {
messages: [
{ from: "Bob", to: "Alice", content: "Hello, Alice!" },
{ from: "Alice", to: "Bob", content: "Hi, Bob!" },
{
from: "Bob",
to: "Alice",
content: `What is the difference between accessing the state directly
rathen than using a getter?`
},
{
from: "Alice",
to: "Bob",
content: `This is your last chance.
After this, there is no turning back.
You take the blue pill—the story ends,
you wake up in your bed and believe whatever you want to believe.
You take the red pill—you stay in Wonderland,
and I show you how deep the rabbit hole goes.
Remember: all I'm offering is the truth. Nothing more.`
}
]
},
getters: {
messages: state => state.messages
}
}
}
});
I have to update the RedPill
computed data:
export default {
name: "HelloWorld",
computed: {
messages() {
return this.$store.state.messages.messages;
}
}
};
But not the BluePill
's one.
export default {
name: "HelloWorld",
computed: {
messages() {
return this.$store.getters.messages;
}
}
};
And that is the same about adding a new feature.
Let's say messages are updated to have a boolean that expresses the need to be displayed or not: draft: true
.
You just need to update the getter and everything is right:
getters: {
messages: state => state.messages.filter(message => !message.draft)
}
That is an introduction to coupling in software development.
A complete codesandbox is available if you want to play with the code.