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.

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

The state

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

<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

<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

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/

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