Using Vue Observable as a lightweight state management alternative to Vuex
Tags: javascript, vue, observable, vuex
Published: 2019-05-09 00:54:12

---
title: Using Vue Observable as a lightweight state management alternative to Vuex
published: true
description: Using Vue Observable as a lightweight state management alternative to Vuex

tags: javascript, vue, observable, vuex
---

[__Vuex__](https://vuex.vuejs.org/) is great for the right application but since it imposes a lot of limitations on how you can change data in your store, it may not be ideal for simpler use cases.

[Vue Observable](https://vuejs.org/v2/api/#Vue-observable) introduced in Vue v2.6.0 could be a lightweight alternative to statement management in smaller applications. I recently used it in a way similar to Vuex ie. reference a state property using __getters__ and manipulate the state using __mutations__ without actually accessing the store directly. 

So lets create a store with an object `users` :

(_Sorry about the contrived example, I'm writing for the first time so couldn't think of anything better._)

```javascript
import Vue from "vue";

const state = Vue.observable({
  users: {
    c6676a9aca4c270086ef31a35cc80446: {
      name: "Ibrahim Ezzy",
      twitter: "3zzy",
      bio: "Software Imagineer. Front-end, UI & Design."
    },
    "4d50982553c3286d65182075c178245f": {
      name: "Tim Apple",
      twitter: "tim_cook",
      bio: "Chief Executive Officer of Apple"
    }
  }
});
```

A generic `setState` method to update any object within the state:

```javascript
const mutations = {
    setState({ object, objectPath, value, upsert = false } = {}) {
        console.log("setState args: ", { object, objectPath, value, upsert });
        if (state[object] === undefined || value === undefined)
            console.error("setState: Invalid Object or Value");
        if (objectPath === undefined) state[object] = value;
        if (objectPath && Array.isArray(objectPath) && objectPath.length) {
            let navigate = [object, ...objectPath.slice(0, -1)],
            valueObj = navigate.reduce((obj, prop) => {
                if (typeof obj[prop] !== "object") {
                if (upsert) {
                    obj[prop] = {};
                } else {
                    console.error(`setState: property '${prop}' doesn't exist`);
                }
                }
                return obj[prop];
            }, state);
            Vue.set(valueObj, objectPath[objectPath.length - 1], value);
        }
    }
    // other specific mutations ...
};
```

And a generic `getState` method to get any object from the state:

```javascript
const getters = {
    getState({ object, objectPath } = {}) {
        if (state[object] === undefined) console.error("getState: Invalid Object.");
        if (objectPath === undefined) return state[object];
        if (objectPath && Array.isArray(objectPath) && objectPath.length) {
            let navigate = [object, ...objectPath.slice(0, -1)],
            valueObj = navigate.reduce((obj, prop) => {
                if (obj[prop] === undefined) {
                console.error(`getState: property '${prop}' doesn't exist`);
                }
                return obj[prop];
            }, state),
            value = valueObj[objectPath[objectPath.length - 1]];
            if (value === undefined) console.error(`getState: Invalid object path`);
            return value;
        }
    }
    // other specific getters ...
};

```

Now you can access the `users` like so:
```javascript
data() {
    return {
        users: getters.getState({
            object: "users"
        })
    };
}
```
and update (or create) using `setState`:
```javascript
methods: {
    updateName(e, id) {
        console.log(e.target.innerText, id);
        mutations.setState({
            object: "users",
            objectPath: [id, "name"],
            value: e.target.innerText
        });
    }
}
```
Probably the most interesting part here are the dynamic `getState` and `setState` methods that can create, update, or access deeply nested properties within the state. Of course these functions aren't perfect and they just work with `Objects` for now, but you get the idea. 

Here's a demo on [CodeSandbox](https://codesandbox.io/s/zn85x6pr1p?fontsize=14).