Setting up the MobX store

After installing MobX, it is time to set up our MobX store. The store will store all state, and the related computed values and actions. It is usually defined with a class.

Let's define the MobX store now:

  1. Create a new src/store.js file.
  2. Import the observable, action, and computed decorators, as well as the decorate function from MobX. These will be used to tag various functions and values in our store:
import { observable, action, computed, decorate } from 'mobx'
  1. Also import the fetchAPITodos and generateID functions from our API code:
import { fetchAPITodos, generateID } from './api'
  1. Now, we define the store by using a class:
export default class TodoStore {
  1. In this store, we store a todos array, and the filter string value. These two values are observables. We are going to tag them as such later on:
    todos = []
filter = 'all'
With a special project setup, we could use an experimental JavaScript feature, known as decorators, to tag our values as observables by writing @observable todos = []. However, this syntax is not supported by create-react-app, since it is not part of the JavaScript standard yet.
  1. Next, we define a computed value in order to get all of the filtered todos from our store. The function will be similar to the one that we had in src/App.js, but now we will use this.filter and this.todos. Again, we have to tag the function as computed later on. MobX will automatically trigger this function when needed, and store the result until the state that it depends on changes:
    get filteredTodos () {
switch (this.filter) {
case 'active':
return this.todos.filter(t => t.completed === false)

case 'completed':
return this.todos.filter(t => t.completed === true)

default:
case 'all':
return this.todos
}
}
  1. Now, we define our actions. We start with the fetch action. As before, we have to tag our action functions with the action decorator at a later point. In MobX, we can directly modify our state by setting this.todos. Because the todos value is observable, any changes to it will be automatically tracked by MobX:
    fetch () {
fetchAPITodos().then((fetchedTodos) => {
this.todos = fetchedTodos
})
}
  1. Then, we define our addTodo action. In MobX, we do not use immutable values, so we should not create a new array. Instead, we always modify the existing this.todos value:
    addTodo (title) {
this.todos.push({ id: generateID(), title, completed: false })
}
As you can see, MobX takes a more imperative approach, where values are directly modified, and MobX automatically keeps track of the changes. We do not need to use the rest/spread syntax to create new arrays; instead, we modify the existing state array directly.
  1. Next up is the toggleTodo action. Here, we loop through all of the todos and modify the item with a matching id. Note how we can modify items within an array, and the change will still be tracked by MobX. In fact, MobX will even notice that only one value of the array has changed. In combination with React, this means that the list component will not re-render; only the item component of the item that changed is going to re-render. Please note that for this to be possible, we have to split up our components appropriately, such as making separate list and item components:
    toggleTodo (id) {
for (let todo of this.todos) {
if (todo.id === id) {
todo.completed = !todo.completed
break
}
}
}
The for (let .. of ..) { construct will loop through all items of an array, or any other iterable value.
  1. Now, we define the removeTodo action. First, we find the index of the todo item that we want to remove:
    removeTodo (id) {
let index = 0
for (let todo of this.todos) {
if (todo.id === id) {
break
} else {
index++
}
}

  1. Then, we use splice to remove one element—starting from the index of the found element. This means that we cut out the item with the given id from our array:
        this.todos.splice(index, 1)
}
  1. The last action that we define, is the filterTodos action. Here, we simply set the this.filter value to the new filter:
    filterTodos (filterName) {
this.filter = filterName
}
}
  1. Finally, we have to decorate our store with the various decorators that we mentioned earlier. We do this by calling the decorate function on our store class and passing an object mapping values and methods to decorators:
decorate(TodoStore, {
  1. We start with the todos and filter values, which are observables:
    todos: observable,
filter: observable,
  1. Then, we decorate the computed value—filteredTodos:
    filteredTodos: computed,
  1. Last but not least, we decorate our actions:
    fetch: action,
addTodo: action,
toggleTodo: action,
removeTodo: action,
filterTodos: action
})

Now, our MobX store is decorated properly and ready to be used!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.13.255