Skip to content

Latest commit

 

History

History
397 lines (251 loc) · 15 KB

Mobx.md

File metadata and controls

397 lines (251 loc) · 15 KB

Mobx State Tree

mobxjs/mobx-state-tree

Mobx-State-Tree is an opinionated library that imposes a strict architecture on state organization.

State is stored in an immutable, structurally shared tree.

Business logic removed from the UI (views are passive) (decouple domain logic and stare from UI) Provides a structure for communication
Embrace composition and reactivity
Relay on the computed properties not on the model Subscribe to all the path streams (patches) Replay and record snapshots, patches and actions Protection against uncoordinated modifications Protection against stale reads Runtime type checking and inferred TypeScript static type checks, design time type checking

A good model makes it easier to deal with reality

State is not just data but identities and relations Separates consumption of data and changing of state

Everything that can be derived from state should be derived. Automatically

Break into smaller components if not fast enough

With observable data we know what changed and where it is relevant resulting in code which is straight forward to read and write, smart optimized rendering and easy separation of concerns

State requires mutability - it's impossible to build a meaningful application without mutability Control mutability and side-effects in an organized way (state management)

Observable objects are as a collection of streams, one stream per property

Use hooks for local state (if it's not needed anywhere outside the component)

Mobx is like a spreadsheet

  • Observables - spreadsheet's data cells that have values (state than can be changed over time)
  • Actions - the act of changing the values of spreadsheet's data cells (interactions that change state)
  • Computed Values - formulas and charts that can be derived from the data cells and other formulas (values that can be derived)
  • Reactions - drawing the output of a data cell or a formula (side effects that should respond to state changes)

observer - turn components into reactive components inject - connects components to provided stores

Mobx compared to Angular/Vue/Knockout

Independent solution (use with anything) Distinct concepts: Side effect and derived values No change detection but change propagation Synchronous scheduling (helps with debugging) Optimally sorted dependency tree for guaranteed glitch-free, minimal amount of computations

Tree

A node can exist only once in a Tree Any node in a Tree is a Tree itself All leaves in the Tree must be serializable Every change to a model correspond to a snapshot and a patch

Tree consists of 2 thing:

  • state (contents)
  • shape (type)
const Type = types.model(properties, actions);
const instance = Type.create(snapshot);
instance.someAction();

const snapshot = getSnapshot(instance);
const Book = types.model(
  {
    title: types.string,
    price: types.number,
  },
  {
    setPrice(newPrice) {
      this.price = newPrice;
    },
  }
);

const Store = types.model({
  books: types.array(Book),
});

const store = Store.create({
  books: [
    {
      title: "Some Title",
      price: 29.99,
    },
  ],
});

store.books[0].setPrice(99.99);

//composing types
store.books.push(Book.create({ title: "Some Title" }));
store.books.push({ title: "Some Title" });

//references

const cartEntry = types.model({
  amount: types.number,
  book: types.reference(Book), //it's not a Book, it's just a reference
});

cartEntry.book = bookStore.books[0]; //normalization done behind the scenes  and reference management

Feature Comparison

Stores

One root store - can preform actions on everything at once, DI is shared

Multiple root stores - easier to reason by Domain (isolation), can't easily preform actions on everything, DI isn't shared

Store Communication

Each Store access directly other Stores getParent(self).someStore - each store knows the whole structure Actions wrapper - calls directly other Stores, knows the whole structure Dependency Injection - injecting stores into one another, can be used for both Actions and Views

const firstStore = FirstStore.Create({});
const secondStore = SecondStore.Create({ someProperty: "Foo" }, { firstStore });

Store Composition

When data is the same but the behavior is different

const thirdStore = types.compose(FirstStore, SecondStore);

  • separation of concerns
  • reusability

Actions

instances can only be modified through actions
actions can only modify own subtree

store.books[0].price = 99.99; //Error cannot modify the object is protected

Method invocation produces action description

//MST is fully recursive concept, every node in the tree is state tree in it self and any operation in the tree can be invoked on a node
const bookCopy = clone(store.books[0]);
const recorded = recordActions(bookCopy);

recorder.replay(store.books[0]); //atomic commit of all the changes the user made

Environment

import { getEnv } from "mobx-state-tree";

Comparison

React Context - single event per context
Redux - global event, but selecting relevant parts
MobX - event per property, selection is automatic (subscribed to each individual property)

React state - component Redux - single store MobX - user defined objects/classes

Both Redux and MobX have decouple state from UI layer

Most bugs happen because poor references management - staleness bugs (store id reference not the object reference, identity or value)

How does MobX works

  • Wrap properties with getter and setter - tracks every interaction with an object
  • Store running function in a stack
  • Getters register observers
  • Setters notify observers
  • MobX optimizes dependency graph (small as possible, least amount of computations)

Transparent reactive programming

  • decoupling of producers and consumers of information
  • straightforward to write
  • optimized, minimal dependency tree

React but for Data

Both React and MST are contract based (only props, views and actions are exposed, internal state encapsulated, design and runtime type checking)

Component - Type (React composes Components, Mobx composes Types)

const House = () => (
  <Door />
  <Window>
)

const House = types.mode({
  doors: Door,
  windows: Window
})

Props - Snapshot

State - Volatile state

Instance - Instance (React composes a tree of component instances, Mobx composes a tree of rich type instances)

const instance = React.createElement(Component, props);
const instance = Type.create(snapshot);

Context - Environment

Reconciliation - Reconciliation (preserve internal state, performance)

Snapshots are immutable, structurally shared representation of entire state at a specific moment in time (GIT Commit)

JSON Patch - deltas describing updates that were applied to the tree (Git Patch, describes modifications from one commit to the next) (used for time travelling like Git Revert, Git Rebase)

Middleware - intercept action invocations (Git hook)

Asynchronous processes in MST

Built in concept based on generators so middleware can run on every continuation

//same semantics, slightly difference syntax
async function - process(function*)
//same semantics, slightly difference syntax
await -yield;

Talks

Next generation state management - Michel Weststrate aka @mweststrate at @ReactEurope 2017

Next generation state management

You don’t know MobX State Tree | Max Gallo | iJS London 2018

 You don’t know MobX State Tree

Introduction to MobX State Tree

Introduction to MobX State Tree

Michel Weststrate: React, But For Data — ReactNext 2017

Michel Weststrate: React, But For Data — ReactNext 2017

Combining GraphQL + mobx-state-tree - Michel Weststrate (@mweststrate) @ReactEurope 2019

Combining GraphQL + mobx-state-tree - Michel Weststrate (@mweststrate) @ReactEurope 2019

MobX State Tree React pure reactivity served - Luca Mezzalira

MobX State Tree React pure reactivity served

Chain React 2019 - Devlin Duldulao - Getting Started with Mobx State Tree

Devlin Duldulao - Getting Started with Mobx Statetree

React Native EU 2019: Jamon Holmgren — Resolving the great state debate

React Native EU 2019: Jamon Holmgren — Resolving the great state debate

Michel Weststrate — State management beyond the libraries

Michel Weststrate — State management beyond the libraries

ReactiveConf 2018 - Michel Weststrate: State management beyond the libraries

ReactiveConf 2018 - Michel Weststrate: State management beyond the libraries

MobX - Statement Management with no Boilerplate - React Native London - March 2020

MobX - Statement Management with no Boilerplate

MobX, or: Going from Mutable to Immutable to Reactive State Management - Michel Weststrate - CityJS

MobX, or: Going from Mutable to Immutable to Reactive State Management

Michel Weststrate: MobX: The Quest For Immer Mutable State Management

MobX: The Quest For Immer Mutable State Management

Michel Weststrate — MobX and the unique symbiosis of predictability and speed

Michel Weststrate — MobX and the unique symbiosis of predictability and speed

Michel Weststrate - Modern React and the case for Reactive State Management

Michel Weststrate - Modern React and the case for Reactive State Management

Mattia Manzati - Advanced Types in TypeScript

Mattia Manzati - Advanced Types in TypeScript

Flutter Reactive State Management With MOBX | Flutter Stream Day Season 1

Flutter Reactive State Management With MOBX | Flutter Stream Day Season 1

Max Gallo - Reinventing MobX

Max Gallo - Reinventing MobX

Advanced state management patterns with JavaScript & MobX with Michel Weststrate

Advanced state management patterns with JavaScript & MobX with Michel Weststrate

Michel Weststrate: Real World MobX — ReactNext 2016

Michel Weststrate: Real World MobX — ReactNext 2016

React Amsterdam Autumn Meetup: MobX and Large Scale React Applications

React Amsterdam Autumn Meetup: MobX and Large Scale React Applications

Spreadsheets with MobX and react-virtualized

Spreadsheets with MobX and react-virtualized

Courses

Manage Application State with Mobx-state-tree

Manage Complex State in React Apps with MobX

Immutable JavaScript Data Structures with Immer

How do I work with state in React?
How do I work with state in React?

What is MobX-State-Tree and how can it help me with React?
What is MobX-State-Tree and how can it help me with React?

How do I get started with MobX-State-Tree and React?
How do I get started with MobX-State-Tree and React?

How do I modify state values in React with MobX-State-Tree?
How do I modify state values in React with MobX-State-Tree?

How do I create views with MobX-State-Tree?
How do I create views with MobX-State-Tree?

Blogs

The Curious Case of Mobx State Tree

Why Infinite Red uses MobX-State-Tree instead of Redux

Understanding MobX and MobX State Tree

State Management with MobX State Tree

mst-gql

https://github.com/mobxjs/mst-gql

Bindings for mobx-state-tree and GraphQL Run scaffolding in your CI/CD against production endpoint to verify readiness

yarn mst-gql --format ts http://localhost:4000/graphql

Combining GraphQL + mobx-state-tree

Stop defending all the choices you don't make. "Didn't try" is fine. You have to learn to be able to use, but, you don't have to use to be able to learn. (read a bit, grab an idea, software engineering is all about patterns)

Tips

If the property was typed as Type | CreationType then all the properties unique to the Type (e.g. actions, views, etc) wouldn't be available when trying to use the property.

To overcome this you have to either cast it to the instance type (since internally mst will convert the snapshot to an instance) or create the instance directly.

Ref