Vuex: why we don’t need it

I asked myself: Why do I need Vuex? I did not find a good answer. Here is why I question the value of Vuex.

I found this article:
https://blog.logrocket.com/vuex-why-we-need-spa-state-management/

Which does not really answer, why? It explains what Vuex does, but why can you not do that with a simple service?

I forked that repo and re-wrote it without Vuex and with an ApplicationService that takes care of state management.

Code comparison

Here are the interesting code to compare between:

The state

The Vuex code is here:
https://github.com/malgamves/vuex-remindrr-app/blob/master/src/store.js

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

export default new Vuex.Store({
state: {
username: "danielphiri",
tasks: [
{ taskName: "take pictures", taskReciever: "mom and dad" },
{ taskName: "email organisers slides", taskReciever: "myself" },
{ taskName: "send resume", taskReciever: "dev job" },
]
},
getters: {
taskCount: state => {
return state.tasks.length;
}
},
mutations: {
ADD_TASK: (state, task) => {

state.tasks.push(task);
},
REMOVE_TASK: (state, task) => {
state.tasks.splice(task, 1);
},
REMOVE_ALL: state => {
state.tasks = [];
}
},
actions: {
removeTask: (context, task) => {
context.commit("REMOVE_TASK", task);
},
removeAll({ commit }) {
return new Promise((resolve) => {
setTimeout(() => {
commit("REMOVE_ALL");
resolve();
}, 2000);
});
}
}
});

My service code is here:
https://github.com/tomasbjerre/not-vuex-remindrr-app/blob/master/src/services/ApplicationService.ts

export interface TodoTask {
taskName: string;
taskReciever: string;
}

export interface MainModel {
username: string;
}

export interface ApplicationState {
mainModel: MainModel;
tasks: TodoTask[];
}

export class ApplicationService {
private state: ApplicationState = {
mainModel: {
username: "tomasbjerre",
},
tasks: [
{ taskName: "take pictures", taskReciever: "mom and dad" },
{ taskName: "email organisers slides", taskReciever: "myself" },
{ taskName: "send resume", taskReciever: "dev job" },
],
};

public getMainModel(): MainModel {
return this.state.mainModel;
}

public getTasks(): TodoTask[] {
return this.state.tasks;
}

public addTask(taskName: string, taskReciever: string): void {
this.state.tasks.push({ taskName, taskReciever });
}

public removeTask(taskIndex: number): void {
this.state.tasks.splice(taskIndex, 1);
}

public removeAllTasks(): void {
this.state.tasks.splice(0, this.state.tasks.length);
}
}

export default new ApplicationService();

Usage in Main.vue

The Vuex code is used here:
https://github.com/malgamves/vuex-remindrr-app/blob/master/src/components/Main.vue

<script>
import { mapState, mapMutations, mapActions } from "vuex";

export default {
name: "Main",
data() {
return {
taskName: "",
taskReciever: "",
};
},
computed: {
...mapState(["tasks", "username"])
},
methods: {
...mapMutations(["ADD_TASK"]),
...mapActions(["removeTask"]),
addTask: function() {
let newTask = Object.create(null);
newTask["taskName"] = this.taskName;
newTask["taskReciever"] = this.taskReciever;
this.ADD_TASK(newTask);
this.taskReciever = "";
this.taskName = "";
},
removeTasks: function(task) {
this.removeTask(task);
}
}
};
</script>

My service code is here:
https://github.com/tomasbjerre/not-vuex-remindrr-app/blob/master/src/components/Main.vue

<script lang="ts">
import { ApplicationService } from "@/services";
import Vue from "vue";

export default Vue.extend({
name: "Main",
data() {
return {
taskName: "",
taskReciever: "",
mainModel: ApplicationService.getMainModel(),
tasks: ApplicationService.getTasks(),
};
},
methods: {
addTask: function () {
ApplicationService.addTask(this.taskName, this.taskReciever);
},
removeTasks: function (taskIndex: number) {
ApplicationService.removeTask(taskIndex);
},
},
});
</script>

Usage in Stats.vue

The Vuex code is used here:
https://github.com/malgamves/vuex-remindrr-app/blob/master/src/components/Stats.vue

<script>
import { mapGetters, mapActions, mapMutations, mapState } from 'vuex'

export default {
name: 'Stats',
computed: {
...mapGetters(['taskCount']),
...mapState(["username"])
},
data() {
return {
message: ""
}
},
methods: {
...mapMutations(['REMOVE_ALL']),
...mapActions(['removeAll']),
removeAllTasks() {
this.removeAll().then(() => {
this.message = 'Self care - tasks are gone'
});
}
}
}
</script>

My service code is here:
https://github.com/tomasbjerre/not-vuex-remindrr-app/blob/master/src/components/Main.vue

<script>
import { ApplicationService } from "@/services";

import Vue from "vue";
export default Vue.extend({
name: "Stats",
data() {
return {
message: "",
mainModel: ApplicationService.getMainModel(),
tasks: ApplicationService.getTasks(),
};
},
methods: {
removeAllTasks() {
ApplicationService.removeAllTasks();
this.message = "Self care - tasks are gone";
},
},
});
</script>

Conclusions

Vuex is something you need to understand. That is true, regardless of how complicated Vuex is. Explicit method calls, that I use in my service, is something most developers are familiar with, you don’t even need to be a frontend developer to understand it.

You do not need Vuex to hold your global application state. I have shown that you can do that in a singelton service.

You do not need Vuex to get reactivity. You can achieve that by returning objects from the service, and mutate (not replace) those objects when working with your state.

One problem with my service is that the objects returned from the service can be mutated by the components. With Vuex you can avoid that. But if you do not need reactivity, you can just return a copy from the service and it is solved.

--

--

--

http://tomasbjerre.se/

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Using MessageFormat with Transloco

Longest Common Prefix

Gamifying a Birthday Fundraiser

Adding Swipe Functionality Using Vanilla JavaScript

React Native Mux Direct Upload

[Action required] Your RSS.app Trial has Expired — Fri Feb 04 2022

Drawing Basic Charts with React, TypeScript & d3. Part I — Line, Area, and Bar Charts.

rawsqljs — Generate Javascript code snippet from SQL file

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Tomas Bjerre

Tomas Bjerre

http://tomasbjerre.se/

More from Medium

vue.js cons ?

How to validate a custom form component in Vue 3?

How to add fontawesome icons to Vuejs