SatchelJS

State Management You Should Check Out

A not-quite Lightning Talk

What the heck is SatchelJS?

Microsoft created SatchelJS to support their Office 365 rewrite in React.

SatchelJS

  • uses a slightly modified Flux implementation
  • borrows some ideas from Redux
  • is built on top of MobX

Flux

  1. Views send actions to the dispatcher.
  2. The dispatcher sends actions to every store.
  3. Stores send data to the views.

Redux

  1. Single source of truth
  2. State is read-only
  3. Changes are made with pure functions

MobX

  1. Observable State
  2. Reactions
  3. Actions

SatchelJS

  1. Type-safe by default
  2. Supports managing multiple concurrent Stores
  3. Leverages MobX Observables

Core Concepts

  1. Store
  2. Actions
  3. Observers
  4. Mutators
  5. Orchestrators

Stores

  • House the state of your application
  • Have a defined structure
  • Are all technically part of one Global store

Actions

  • Send data to Mutator, Orchestrator, or combination thereof
  • Are created using an actionCreator
  • Can be dispatched at will

Observers

  • Allow MobX to notify Components of changes in the Store
  • Automatically keeps Component in sync with the state of the Store

Mutators

  • Listen for an Action
  • Actually mutate the state in a Store
  • Should not trigger any Actions or side effects

Orchestrators

  • Connect to an external source
  • Listen for an Action
  • Can dispatch multiple Actions during their life cycle

Examples

import { createStore } from 'satcheljs';

// this creates a Symbol that will be returned
// when you call this method again
export default createStore(
    'todoStore',
    { todos: [] },
);

Creating a Store

import { action } from 'satcheljs';

export default action(
    'ADD_TODO',
    (text: string) => ({ text: text }),
);

Creating an Action

import { mutator } from 'satcheljs';

import todoStore form '../store';

import { ADD_TODO } from '../actions';

export default mutator(ADD_TODO, (actionMessage) => {
    const store = todoStore();

    store.todos.push({
        id: Math.random(),
        text: actionMessage.text,
    });
};

Creating a Mutator

import { action, orchestrator, dispatch } from 'satcheljs';

import { RECEIVE_TODOS, ADD_TODO } from '../actions';

export default orchestrator(RECEIVE_TODOS, async () => {
    // let's grab any todos our user has saved on our server
    await fetch(process.env.TODO_SERVER)
        .then(response => response.json())
        .then(data => {
            data.forEach(todo => dispatch(ADD_TODO, todo)
        })
    ;
};

Creating an Orchestrator

import React, { Component } from 'react';

import { observer } from 'mobx-react';

import todoStore from '../store';

const mapTodos = todos => todos.map(todo => <li>{todo.text}</li>);

@observer
// if you're gonna use decorators, you have to use a Class
// instead of a just a functional Component
export default class TodoListComponent extends Component {
    private store = todoStore();

    render() {
        const { todos } = this.store;

        return (
            <ol>
                {mapTodos(todos)}
            </ol>
        );
    }
}

Creating a Reactive Component

Why choose SatchelJS?

  • Simple: less boilerplate
  • Performant: intelligent reactive updates
  • Type-Safe: integrates directly with TypeScript

Are there any drawbacks?

  • Documentation: There isn't a lot out there; like seriously, there is very little documentation
  • Support: There appears to only be a handful of people at Microsoft who work on it and they are busy rewriting Outlook.com and Office365 with it
  • Roadmap: There doesn't seem to be any clearly published roadmap or overall vision for the project and it's mostly just one Microsoft employee making updates

Fin.

SatchelJS

By Eric Allen

SatchelJS

  • 779