Understanding ...mapGetters in Vuex
Tags: javascript, beginners, webdev, vue
Published: 2019-08-14 11:58:45

---
title: Understanding ...mapGetters in Vuex
published: true
description: I was recently working with vuex and came across a piece of code I wanted to learn more about.
tags: javascript, beginners, webdev, vue
series: Boilerplate Basics
cover_image: https://thepracticaldev.s3.amazonaws.com/i/byn1ggti8grencuz6pv0.jpg
canonical_url: https://tenmilesquare.com/understanding-mapgetters-in-vuex/
---

In `vuex` there is a helper function that shows up a lot.

```javascript
computed() {
    ...mapGetters(['currentUser'])
}
```

When I was first working with it, I had some babel issues preventing me from using ES6 syntax and as a result, I couldn't use the function as intended. Using the workaround helped me understand exactly what this small snippet was doing, so I thought I'd write it up.

As it turns out, there are a couple of things happening here. One is what `mapGetters` does as a function, and the other is how the spread syntax transforms the result. Let's start by diving into the function itself.

### What is mapGetters?

In our example the purpose of `mapGetters` is to map the result of `store.getters.currentUser` to the computed attribute `currentUser`. This allows us to access the result of our getter function like so.

```html
<div>{{currentUser}}</div>
```

As it turns out, `mapGetters` can take an object or an array. So this snippet, which is shown above.

```javascript
computed() {
    ...mapGetters(['currentUser'])
}
```

Can also be this.

```javascript
computed() {
    ...mapGetters({currentUser: 'currentUser'})
}
```

In the first case the name assignment is implicit, in the second it's explicit. But that's the only difference.

Now that we know what the function is doing, let's break it down.

> I'm always in favor of having multiple different ways to understand concepts. So, I asked my coworker to read this post and his explanation of what `mapGetters` was doing went like this. 
"The idea is to take a set of variables in your store object in a view controller, and map them to a top-level getter function you can call by name from the two way binding on the html page?"

### mapGetters

Let's say that we aren't able to use the function or helper syntax at all. In order to accomplish the same thing, what do we need to do?

We want to call our getter function, return the result and make that result accessible via some sort of name. So we'd do this.

```javascript
computed() {
    currentUser() {
         return this.$store.getters.currentUser;
    }
}
```

We're creating a function and returning the result of our getter function inside of it. The result can be accessed using that function name, as in this example.

```html
<div>{{currentUser}}</div>
```

Keep in mind that the name we're using is the name of the computed function, NOT the name of the getter method we're calling. Take this example where the names aren't the same.

```javascript
computed() {
    otherName() {
         return this.$store.getters.currentUser;
    }
}
```

In order to access the result, we'd reference `otherName`.

```html
<div>{{otherName}}</div>
```

A lot of this binding comes from Vue. You can read more [here](https://vuejs.org/v2/guide/computed.html).

### Deep cut

If you want to really deep dive, here is the source code for `mapGetters`.

```javascript
/**
 * Reduce the code which written in Vue.js for getting the getters
 * @param {String} [namespace] - Module's namespace
 * @param {Object|Array} getters
 * @return {Object}
 */
export const mapGetters = normalizeNamespace((namespace, getters) => {
  const res = {}
  normalizeMap(getters).forEach(({ key, val }) => {
    // The namespace has been mutated by normalizeNamespace
    val = namespace + val
    res[key] = function mappedGetter() {
      if (
        namespace &&
        !getModuleByNamespace(this.$store, 'mapGetters', namespace)
      ) {
        return
      }
      if (
        process.env.NODE_ENV !== 'production' &&
        !(val in this.$store.getters)
      ) {
        console.error(`[vuex] unknown getter: ${val}`)
        return
      }
      return this.$store.getters[val]
    }
    // mark vuex getter for devtools
    res[key].vuex = true
  })
  return res
})
```

There is a lot here, and some of that is to handle the difference in the object versus array input, but the meat of it is in the `mappedGetter` function. It takes the return object, and using the given key, assigns the result of the associated getter function to the value.

### Multiple

Now that we understand the function itself, let's turn our attention to the spread syntax. The key to understanding `...mapGetters` really comes from recognizing that the function is designed to handle multiple getter calls at the same time. The single use case we started with still works, but let's look at this.

```javascript
computed() {
    currentUser() {
         return this.$store.getters.currentUser;
    }
    otherThing() {
         return this.$store.getters.otherThing;
    }
    finalThing() {
         return this.$store.getters.finalThing;
    }

}
```

We're taking the result of our getter functions and assigning them to function variables we can reference inside our component. It's the same thing we did above, just for multiple getter calls at the same time.

Doing this allows us to render all of these results.

```html
<div>{{currentUser}} {{otherThing}} {{finalThing}}</div>
```

Now it's easier to explain the `...` in front of mapGetters.

### Spread Syntax

You may be familiar with ES6 spread syntax. If you want a refresher I wrote a post on it here.
{% link https://dev.to/laurieontech/5-uses-for-the-spread-operator-b9i %}

It's a powerful piece of syntax that can do a number of different things. But let's see what it's doing in our example.

We've seen that `mapGetters` is designed to replace multiple function calls. When it resolves, it returns an object that consists of key-value pairs. Each key is a string name, and each value is the result of the associated getter function call. So really, we're left with something like this.

```javascript
computed() {
    ...{'currentUser': currentUser, 'otherThing': otherThing, 'finalThing': finalThing}
}
```
*Note that this is not valid JavaScript! It's just an abstraction.*

As it turns out, that looks an awful lot like an object literal. And how does the spread syntax handle object literals? It acts as `Object.assign()`.

If you're unclear what that means, it's really accomplishing the following. The spread syntax selects each key-value pair inside the object and pulls it out as a stand-alone object. So each key can be used to reference the value that stores the result, just like we saw before.

```html
<div>{{currentUser}} {{otherThing}} {{finalThing}}</div>
```

### All Together Now

Let's look at our code from the very beginning.

```javascript
computed() {
    ...mapGetters(['currentUser', 'otherThing', 'finalThing'])
}
```

Can we see what's happening now? Each string in the array is processed by `mapGetters`. It takes the getter method of the same name and calls it, then it assigns the result as the value where the key is the original string. 

`mapGetters` returns an object with a series of key-value pairs based on that formula. Then, the spread syntax plucks out each of those key-value pairs to be a stand-alone object that can be referenced directly inside the template code. And that's everything.

### Conclusion

That was a lot! And you may never use mapGetters. But it's kind of cool to understand it, right?