Codementor Events

To-Do app: Composition API as an alternative to Vuex

Published Oct 10, 2020Last updated Apr 08, 2021
To-Do app: Composition API as an alternative to Vuex

After reading an Anthony Gore's article about using the new Composition API as some sort of replacement of Vuex, for smaller projects, I took a simple todo app I built in Codepen, and then I created a new Vue 3 app (using the vue cli) and lastly, I moved all the state and mutation methods from each component to one single file (global.js - which will be something like the store, in Vuex).

Source code and foreword

Here's a list of the source code and the Codepen I will refer to in this article:

Codepen: Vue To-do app

GitHub repo: todo-app-vue3

Netlify: https://relaxed-yonath-fa8475.netlify.app/

If you take a look at the todo app I created in Codepen you'll notice I'm not even using Vuex, I'm just using both props to pass data down to children and $emit to pass data/communicate up to parent components.

One of the advantages of the new Composition API is that now we have access to reactive features outside of components, which is quite powerful.

So here's what I did after creating my Vue 3 app, and putting the components code into its own files, and basically making the app work like it is working on Codepen:

Move the state and mutation functions to a global file

The first thing I did was to create the global.js file in /src.

Alt Text

Inside global.js, I imported the reactive and the readonly APIs. Let's take a look at the code in 'global.js' - I will add the comments in the code snippet.

import { reactive, readonly } from "vue";

/* 
Wrapping our object with reactive() makes, 
as it clearly suggests, our object reactive 
(it even affects all nested properties).
*/

const state = reactive({
  tasks: [
     {
      id: 1,
      description: "Finish the course",
      done: false,
     }, 
     {..}, 
     {..}, 
     {..}, 
     {..}
  ],
  nextId: 6,
  tasksFiltered: [],
  activeTab: "all",
})

/* 
All these functions below are a combination of
mutations and actions (when comparing with Vuex).
But, of course, we are always free to organize our code
however we want.
*/

const filterTodos = function(filterOption) {..}

const addTodo = function(todo) {..}

const deleteTask = function(task) {..}

const toggleTaskStatus = function(task) {..}

// Export an object with the state and mutations
export default { 
  // With readonly(), we prevent our state to be mutated
  // outside of the global.js module
  state: readonly(state), 
  filterTodos, 
  addTodo, 
  deleteTask, 
  toggleTaskStatus
}

Use Provide / inject

Then, we need to make global.js (our "custom store") accesible to all of the App.vue child components. To do so, we have to use the provide property inside our App.vue in order to make global.js available to all the child components, so we import global.js in App and then, we provide it.

Alt Text

Right after that, in each component, we need to inject global in order to use it on each of them.

Alt Text

Now a screenshot of each child component (but remember, you can always go to the repo and take a look a the code)

TodoList.vue

Alt Text

Form.vue

Alt Text

Header.vue

Alt Text

Alt Text

This approach can be improved, and could serve as a simpler alternative. Of course, Vuex is more debuggable and we can track mutations in the vue dev tools. So it will always depend on the project we're working on or our personal choice and point of view.

What do you think about this approach?
Do you have any suggestions?

Hope you found this article useful! 🙂

Discover and read more posts from Diego Palacios Lepore
get started