DEV Community

Cover image for Should you always use getters in Vuex?
Joe Erickson
Joe Erickson

Posted on • Edited on • Originally published at jerickson.net

Should you always use getters in Vuex?

One of the questions that comes up time and again concerning Vuex is "Do I always use a getter when accessing data? Or can I directly access the raw state?" It's one of those things you hear about that you should do, but no one seems to really explain why. And do you really need to create a getter for every single piece of data that you put in the store? Isn't that just a bunch of unneeded boilerplate and duplication?

Can you directly access Vuex state from a component?

So, first the technical answer: there is nothing stopping you from accessing state directly in a component. In fact, you can do it directly in a component's UI if you want to.

<template>
    <p>
    {{ $store.state.clickCount }} clicks!
  </p>
</template>
Enter fullscreen mode Exit fullscreen mode

Or in any Vue method or computed property, for that matter. Direct state reading is 100% available.

Should you directly access Vuex state from a component?

This is a bit of a different discussion. Just because you can do something doesn't mean that you should do something. At least, that's what my mom always told me. I found it out the hard way when I realized I could drink Mountain Dew through a Twizzler. I did that for a couple of days straight and quickly realized that some things were just not meant to be done.

Is accessing Vuex state directly one of those things? Should you directly access state?

No, you shouldn't

This is what I think of as the Java approach. In Java, all data access of an object's variables is done through what are called Getters. (Sound familiar?) The idea is that allowing direct access to an instance variable is a bad idea. What if you want to change how that instance variable is represented at some point in the future? What if you want to lock down who can set it? What if you want to add validation around the kinds of values you can set on it?

All of the above would break Encapsulation and that's a very bad thing. Many programmers have gravitated to this idea: You must have data access go through a function so that the programmer always has control over how that data is accessed. You might have a getter that just returns the data, but having the getter means that you always have the option of changing how that data is represented or used at any time.

This makes a lot of sense in a rigid language like Java. Java is just not very flexible, so adding in the getters right from the beginning can same you a lot of time down the road. Especially when a lot of Java code is reused across projects and having a standard naming convention (like getters) can really simplify a lot of pieces.

And Java also has types. If you wanted to change what data type a certain piece of data was, it would break any and all code that relied on the old version. But if everything uses getters, you can keep the old getter, make a new getter with a different name and keep everything chugging along very happily.

There is also the idea that if you only use getters in Vuex, you'll never accidentally try to set the value. You can technically set state in a Vuex store, but that's a really bad idea (as I explained in Why should you only change state in Vuex through mutations?). Using only getters will save you from ever accidentally doing this because it will throw an error instead of letting you do it.

EDIT: Alexander Van Maele pointed out in the comments on dev.to that it can also be really useful to use getters when trying to access deeply nested material in the state.

[W]hen accessing beyond two levels, I generally like using a getter. So state.selectedOrder.deliveryTime.date becomes getters.deliveryDate

Another very good reason to use getters as this improves readability in the components by a lot.

Yes, you should

Some will argue (including me) that you should access the state if that's all you need. Why add unneeded complexity to your application? The more lines of code you have, the more places bugs can hide. Only add complexity when you absolutely have to. In this case, when that data needs to be filtered or formatted before being used. This is the same idea of why you write code only to pass the most recent test in TDD. Many object oriented designers swear by this approach too, including my favorite Sandi Metz. Only write the code you need, not the code you think you might need maybe sometime but not now. Code design happens much more organically because you are refactoring as you go and watching for efficiencies that you can add as you add new code.

(An aside: I highly recommend Sandi's book Practical Object Oriented Design for any developer looking at how to design their applications. It is focused on object orientation and the Ruby language, but the principles in there are top notch if you're looking to move to the next level of development.)

With these principles, future changes are easy. Need to use a getter instead of the direct state at some point down the line? Just search and replace it. Code editors are very powerful in this regard now and changing $store.state.clickCount to $store.getter.clickCount in every component in your project can be done and tested in seconds. JavaScript (and even TypeScript) just aren't as rigid as Java is. Use that flexibility to your advantage and don't get caught up in the right way to do things from other languages.

Another reason that Java uses getters all the time is because Java also uses setters to set data. If they gave direct access to the variable, it would be impossible to eventually validate or restrict write access to them if the time ever came to do that. When talking about Vuex, our setters are Mutations, and I've already talked about why those are important to use. They are also a great place to do validation or other checking of the data before actually setting it.

So...

I think a lot of the advice to only access data through getters is trying to apply lessons from other languages to JavaScript and Vue, and I'm not entirely sure they always apply. My main goal is always simplicity and sometimes it's just simpler to access the state directly. The moment it's not, I can add a getter and then run search and replace in my code. Easy and straightforward.

Saying that, I would expect that you'll access most data through getters. They are powerful for filters and formatting and a lot of data is going to benefit from being filtered and formatted.

But many developers are doing it in different ways and it's hard to say if anyone is wrong or 100% right about it. Ultimately the final decision is up to you.

Top comments (3)

Collapse
 
atlesque profile image
Alexander Van Maele • Edited

Great post Joe, thanks!

I agree there is no need for getters if you're accessing a basic, non-computed state. To me, 'basic' means one or at most two levels deep into the state. e.g.
state.selectedOrder.deliveryTime

However, when accessing beyond two levels, I generally like using a getter. So state.selectedOrder.deliveryTime.date becomes getters.deliveryDate

This makes it easier to read components which are using this state imo. If you combine this with ...mapGetters[] you can write very succinct components like:
<span>{{ deliveryDate }}<span>
Instead of:
<span>{{ $state.selectedOrder.deliveryTime.date }}<span>

Collapse
 
firstclown profile image
Joe Erickson

Oh, really good point! I'm going to work on rolling this into the main text, if you don't mind (crediting you, of course). I wouldn't want others to miss it.

Collapse
 
atlesque profile image
Alexander Van Maele

That's great! Feel free to! 😊