Managing State

with mobx

Agenda

The Problem

Mobx Core concepts

Demo App

Redux vs Mobx

The Problem

Manage/Provide state across large and complex component tree

Solutions

Global state container/manger

---- with flavors ----

 

immutable  mutable

passive  reactive

dispatcher  pure function

Mobx

Anything that can be derived from the application state, should be derived. Automatically.

 

Core Concepts

Observable state

import { observable } from "mobx"

class Todo {
    id = Math.random();
    @observable title = "";
    @observable finished = false;
}
import { decorate, observable } from "mobx"

class Todo {
    id = Math.random();
    title = "";
    finished = false;
}
decorate(Todo, {
    title: observable,
    finished: observable
})

Computed Values

class TodoList {
    @observable todos = [];
    @computed get unfinishedTodoCount() {
        return this.todos.filter(todo => !todo.finished).length;
    }
}

Reactions

autorun(() => {
    console.log("Tasks left: " + todos.unfinishedTodoCount)
})

class MyResource {
    constructor() {
        when(
            // once...
            () => !this.isVisible,
            // ... then
            () => this.dispose()
        );
    }

    @computed get isVisible() {
        // indicate whether this item is visible
    }

    dispose() {
        // dispose
    }
}

Reactions

import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {observer} from 'mobx-react';

@observer
class TodoListView extends Component {
    render() {
        return <div>
            <ul>
                {this.props.todoList.todos.map(todo =>
                    <TodoView todo={todo} key={todo.id} />
                )}
            </ul>
            Tasks left: {this.props.todoList.unfinishedTodoCount}
        </div>
    }
}

const TodoView = observer(({todo}) =>
    <li>
        <input
            type="checkbox"
            checked={todo.finished}
            onClick={() => todo.finished = !todo.finished}
        />{todo.title}
    </li>
)

const store = new TodoList();
ReactDOM.render(<TodoListView todoList={store} />, document.getElementById('mount'));

Actions

class TodoStore {
  @observable todos = []

  @action addTodo = (title) => {
    this.todos.push(new Todo(title));
  }
  @action removeTodo = (id) => {
    this.todos.splice(this.todos.findIndex(todo => todo.id === id),1);
  }
  @action updateTodo = (id,newValue) => {
    this.todos.find(todo => todo.id === id).title = newValue;
  }
}

< VS >

MOBX

REDUX

< VS >

MOBX

REDUX

Multiple Stores

Reactive

Observable data structures

Nested state

Mutable

Automatically (tu)

Read/Write state

Impure

Optional Actions

Single Store

Passive

Plain Objects

Normalized state

Immutable

Manually (tu)

Read only state

Pure

Requires Actions

Managing State with mobx

By Salama Ashoush

Managing State with mobx

  • 142