DEV Community

Cover image for Reduce boilerplate with vue-path-store and its Vuex plugin
Giannis Koutsaftakis
Giannis Koutsaftakis

Posted on

Reduce boilerplate with vue-path-store and its Vuex plugin

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/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. 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 and Pinia so that you can use its methods with your favorite state management library.

Quick Example

Install vue-path-store into your app

npm i vue-path-store
Enter fullscreen mode Exit fullscreen mode

Create the store in a separate file (e.g store.js)

// store.js
import { createPathStore } from 'vue-path-store'

// Initialize the store and export it
export const store = createPathStore({
  state: {
    message: 'Hello world'
  }
})
Enter fullscreen mode Exit fullscreen mode

Use it inside components

<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>
Enter fullscreen mode Exit fullscreen mode

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.

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

// 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']
Enter fullscreen mode Exit fullscreen mode

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 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 🎉

Alt Text

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

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
})
Enter fullscreen mode Exit fullscreen mode

Using it inside components

<template>
  <div>
    {{ $store.state.message }}
    <button @click="$store.set('message', 'New message')">
      Set message
    </button>
  </div>
</template>
Enter fullscreen mode Exit fullscreen mode

That's it!

You can view a more detailed Vuex PathStore Plugin example here.

Try PathStore and PathStore Vuex plugin in your next project, you might find that you end up with lighter files and less boilerplate code!

Top comments (0)