How Does MobX Make State Management As Easy As A Spreadsheet?

Unlocking Simplicity: Empower Your Web App State Management with MobX

How Does MobX Make State Management As Easy As A Spreadsheet?

Getting to Know MobX: Making State Management a Breeze

When dabbling with modern web development, one of the trickiest parts is managing the state. If not handled right, it can become a chaotic mess. Enter MobX – the superhero that provides an easy, scalable, and powerful way to manage your application’s state using a concept called functional reactive programming.

MobX: The Basics

MobX makes state management as straightforward as a spreadsheet. Think of your application state as cells in a spreadsheet. MobX ensures that anything derived from this state is automatically updated, thus preventing inconsistencies and making your code more predictable and manageable.

Digging Into MobX’s Core Ideas

Understanding MobX revolves around four main ideas – application state, derivations, reactions, and actions.

Application State

Application state is an assortment of objects, arrays, primitives, and references representing your application’s model. Imagine these values as cells in a spreadsheet. MobX makes these values observable, which means they can be tracked and updated automatically.

import { observable } from 'mobx';

class Store {
  @observable counter = 0;
}

Derivations

Derivations are auto-updating values derived from the application state. For example, you might have a computed value showing unfinished tasks. Derivations only update when their underlying state changes, so no unnecessary calculations are made.

import { computed } from 'mobx';

class Store {
  @observable todos = [];

  @computed get unfinishedTodos() {
    return this.todos.filter(todo => !todo.completed);
  }
}

Reactions

Reactions, on the other hand, are functions that execute automatically when there’s a change in the state. Unlike derivations, they’re used for tasks like updating the DOM or making network requests.

import { when } from 'mobx';

class Store {
  @observable counter = 0;

  constructor() {
    when(
      () => this.counter > 100,
      () => console.log('Counter exceeded 100')
    );
  }
}

Actions

Actions are defined functions that modify the application state. MobX handles all reactions and derivations triggered by actions, ensuring the state remains consistent.

import { action } from 'mobx';

class Store {
  @observable counter = 0;

  @action incrementCounter() {
    this.counter++;
  }
}

Marrying MobX with React

MobX integrates effortlessly with React, creating components that reactively update whenever the state does. Here’s how to get it going:

  1. Install MobX and MobX-React:

    yarn add mobx mobx-react
    
  2. Create an Observable Store:

    import { observable, action } from 'mobx';
    import { observer } from 'mobx-react';
    
    class BooksStore {
      @observable books = [];
    
      @action addBook(book) {
        this.books.push(book);
      }
    
      @action removeBook(book) {
        this.books = this.books.filter(b => b !== book);
      }
    }
    
    const booksStore = new BooksStore();
    
  3. Create Reactive Components:

    import React from 'react';
    import { observer } from 'mobx-react';
    
    @observer
    class BooksList extends React.Component {
      render() {
        return (
          <div>
            <h1>Books List</h1>
            <ul>
              {this.props.booksStore.books.map(book => (
                <li key={book}>{book}</li>
              ))}
            </ul>
            <button onClick={() => this.props.booksStore.addBook('New Book')}>Add Book</button>
          </div>
        );
      }
    }
    
    const App = () => {
      return (
        <div>
          <BooksList booksStore={booksStore} />
        </div>
      );
    };
    

Perks of Using MobX

Less Boilerplate

Unlike other state management libraries, MobX cuts down on unnecessary boilerplate code. You can jump into managing state with minimal setup, which is a blessing for smaller projects or teams that lean towards simplicity.

Scalability

MobX is built to grow with your application. It handles complex state management smoothly, ensuring that your app stays efficient even as it scales.

Flexibility

MobX is quite laid-back about how you organize your app. Whether you’re using different architectural patterns or have specific project needs, MobX accommodates without fuss.

Direct State Mutation

While some state management tools insist on immutability, MobX allows for direct state mutation. This can simplify certain state management tasks, especially when dealing with complex data structures.

Building a Simple Todo App with MobX

Putting theory into practice, let’s create a simple to-do list application using MobX.

Setting Up the Store

First, define the store for your todos.

import { observable, computed, action } from 'mobx';

class TodoStore {
  @observable todos = [];

  @computed get unfinishedTodos() {
    return this.todos.filter(todo => !todo.completed);
  }

  @action addTodo(todo) {
    this.todos.push(todo);
  }

  @action toggleTodo(todo) {
    todo.completed = !todo.completed;
  }

  @action removeTodo(todo) {
    this.todos = this.todos.filter(t => t !== todo);
  }
}

const todoStore = new TodoStore();

Creating Reactive Components

Now, build reactive components that update automatically when the state changes.

import React from 'react';
import { observer } from 'mobx-react';

@observer
class TodoList extends React.Component {
  render() {
    return (
      <div>
        <h1>Todo List</h1>
        <ul>
          {this.props.todoStore.todos.map(todo => (
            <li key={todo.id}>
              <input type="checkbox" checked={todo.completed} onChange={() => this.props.todoStore.toggleTodo(todo)} />
              <span style={{ textDecoration: todo.completed ? 'line-through' : 'none' }}>{todo.text}</span>
              <button onClick={() => this.props.todoStore.removeTodo(todo)}>Remove</button>
            </li>
          ))}
        </ul>
        <input type="text" ref={input => (this.input = input)} />
        <button onClick={() => {
          const todo = { id: Date.now(), text: this.input.value, completed: false };
          this.props.todoStore.addTodo(todo);
          this.input.value = '';
        }}>Add Todo</button>
      </div>
    );
  }
}

const App = () => {
  return (
    <div>
      <TodoList todoStore={todoStore} />
    </div>
  );
};

Wrapping It Up

MobX brings a breath of fresh air to state management by applying functional reactive programming principles. It ensures that your application state remains consistent and up-to-date with less fuss and boilerplate. With its flexibility, scalability, and ease of use, MobX emerges as a strong contender for managing state in modern web applications. Whether your project is a tiny experiment or a sprawling enterprise application, MobX helps keep your code clean, maintainable, and snappy.