Reduce boilerplate with vue-path-store and its Vuex plugin
Tags: vue, javascript, webdev, vuex
Published: 2021-05-30 08:04:18

[vue-path-store](https://github.com/kouts/vue-path-store) (PathStore) is a simple, lightweight, **shared** state management solution for Vue. At its heart lays a reactive object enhanced with generic methods like `set, get, toggle, del, push` that perform data mutation (and retrieval) using the **dot notation** path syntax.

PathStore is perfect for ___simple___ apps, demos and, prototypes, in those cases where you need to have some shared state across components.

#### Highlights
- Lightweight, minified gzip size is < **1.5kb**
- Less boilerplate code, no need to have an `action`/`mutation` for every property of the state you need to update. Of course, you can always create distinct `actions`/`mutations` if you want to.
- Easy to reason about, lodash-like [set](https://lodash.com/docs/latest#set)/[get](https://lodash.com/docs/latest#get) syntax. 
- Use the `set` method to create deep reactive objects. If a portion of the path doesn't exist, it's **created** automatically.
- No need to worry about Vue's [change detection caveats](https://vuejs.org/v2/guide/reactivity.html#Change-Detection-Caveats). The `set` and `del` methods use the `Vue.set` and `Vue.delete` methods under the hood, to ensure reactivity is preserved.
- Set data into multiple properties at once.
- Fail-safe data access using `get`, if the given path does not exist it returns `undefined`.
- Share the store as any other object in Vue. You can use `Vue.prototype`, `a mixin`, `provide/inject`, `import/export` etc
- Comes with plugins for [Vuex](https://vuex.vuejs.org/) and [Pinia](https://pinia.esm.dev/) so that you can use its methods with your favorite state management library.

## Quick Example

Install `vue-path-store` into your app
```sh
npm i vue-path-store
```

Create the store in a separate file (e.g store.js)
```js
// store.js
import { createPathStore } from 'vue-path-store'

// Initialize the store and export it
export const store = createPathStore({
  state: {
    message: 'Hello world'
  }
})
```
Use it inside components
```vue
<template>
  <div>
    {{ store.state.message }}
    <button @click="store.set('state.message', 'New message')">
      Set message
    </button>
  </div>
</template>

<script>
import { store } from './store.js'

export default {
  data() {
    store
  }
}
</script>
```

## Available methods
PathStore provides a set of generic methods to mutate and retrieve data from the store. The first argument of every method is always the `path` of the data to operate on. Both `dot` and `bracket` notation, or a combination of the two, can be used. A more detailed description for each method can be found in the [API docs section](https://vue-path-store.netlify.app/path-store/api/).

| Method                                     | Short description                                |
|--------------------------------------------|--------------------------------------------------|
| `set(path, value)` or `set(map)`           | Sets one or multiple values                      |
| `get(path)`                                | Retrieves a value                                |
| `toggle(path)`                             | Toggles a value to true/false                    |
| `del(path)` or `del(array)`                | Deletes one or multiple properties               |
| `pop(path)`                                | Removes and returns the last element of an array |
| `push(path, value[, ...valueN])`           | Appends elements to the end of an array          |
| `reverse(path)`                            | Reverses an array                                |
| `shift(path)`                              | Removes and returns the first element of an array|
| `sort(path[, compareFunction])`            | Sorts an array                                   |
| `splice(path, index, [removeCount[, add]])`| Removes or replaces array elements               |
| `unshift(path, value[, ...valueN])`        | Inserts elements to the beginning of an array    |

### Some method usage examples

```js
// store is an initialized PathStore instance

// set
// Can be used to set one or multiple properties at once.
// If intermediate path properties don't exist
// they will be created.

store.set('state.foo', 'New value')
// This will set state.foo to 'New value'

store.set({
  'state.arr[1]', 'New array item',
  'state.modal.open', true,
  'state.user': { name: 'John Doe', age: 27 },
  'state.foo.bar': 'Another value here'
})

// toggle
// Switches a boolean value from
// true to false and vice versa

store.toggle('state.bar')
// state.bar is now true

store.toggle('state.bar')
// state.bar is now false

// get
// Retrieves a value
/*
Assuming the data inside the store is
{
  arr: ['test1', 'test2']
}
*/

store.get('arr[1]')
// or
store.get('arr.1')
// Will return 'test2'

// push
// Appends one or more elements to the end of an array
/*
Assuming the data inside store is
{
  arr: ['test1', 'test2']
}
*/

store.push('arr', 'test3', 'test4')
// arr will now be ['test1', 'test2', 'test3', 'test4']
```

## PathStore Vuex Plugin

Vuex is the de-facto solution for centralized state management when it comes to large Vue applications. Often times though creating actions/mutations for every property in your store seems like a bit of unneeded cognitive overhead. 

[PathStore Vuex Plugin](https://vue-path-store.netlify.app/path-store-vuex-plugin/) integrates to Vuex in order to reduce boilerplate and provide a better Vuex development experience overall. This way we can leverage the full power of Vuex and take advantage of Vue Devtools to debug our app as well.

### How it works

When installed, PathStore Vuex Plugin, injects all of PathStore's methods (`set, get, toggle` etc) into Vuex. These methods also trigger equivalent **generic mutations** when called. This way we have full visibility of Vuex mutations history in Vue Devtools :tada:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7vhg4j5768uixonkeuon.png)

Since Vuex modules use the root Vuex state, you can use the PathStore Vuex Plugin methods to set/get the state of **Vuex modules** as well.

Needless to say, **all** Vuex features (getters/actions/mutations,  etc) can be used as before, along with PathStore Vuex Plugin's methods.

### Quick Example
```js
import Vue from 'vue'
import Vuex from 'vuex'
import { pathStoreVuexPlugin } from 'vue-path-store/dist/es/pathStoreVuexPlugin.js'

Vue.use(Vuex)

const store = new Vuex.Store({
  plugins: [pathStoreVuexPlugin],
  state: {
    message: ''
  }
})

new Vue({
  el: '#app',
  store
})
```

Using it inside components
```vue
<template>
  <div>
    {{ $store.state.message }}
    <button @click="$store.set('message', 'New message')">
      Set message
    </button>
  </div>
</template>
```

### That's it!
You can view a more detailed Vuex PathStore Plugin [example here](https://vue-path-store.netlify.app/examples/#todo-using-pathstore-vuex-plugin).

Try [PathStore](https://vue-path-store.netlify.app/) and [PathStore Vuex plugin](https://vue-path-store.netlify.app/path-store-vuex-plugin/) in your next project, you might find that you end up with lighter files and less boilerplate code!