Mobx + React simple todolist

by zerkalica

HTML

<body>
<script crossorigin src="https://unpkg.com/react@next/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@next/umd/react-dom.development.js"></script>
<script crossorigin src="https://unpkg.com/lom_atom@2/dist/lom_atom.umd.js"></script>
<script crossorigin src="https://unpkg.com/reactive-di@4/dist/reactive-di.umd.js"></script>

<div id="mount">
    </div>
</body>

Babel + JSX

// @flow
const {mem, action, force} = lom_atom
const {createReactWrapper, createCreateElement, Injector} = window['reactive-di']
const {render} = ReactDOM
const {createElement, Component} = React

/** @jsx lom_h */

// setup
function ErrorableView({error}: {error: Error}) {
    return <div>
        {error instanceof mem.Wait
            ? <div>
                Loading...
            </div>
            : <div>
                <h3>Fatal error !</h3>
                <div>{error.message}</div>
                <pre>
                    {error.stack.toString()}
                </pre>
            </div>
        }
    </div>
}

  const lomCreateElement = createCreateElement(
      createReactWrapper(
          Component,
          ErrorableView
      ),
      createElement
  )
  window['lom_h'] = lomCreateElement

// todo


let tid = 0
class Todo {
    id = ++tid;
    @mem title;
    
    @mem finished = false;
    constructor(title) {
        this.title = title;
    }
}

function fetchSomeTodos() {
    return new Promise(resolve => {
        setTimeout(() => resolve([
            new Todo('Get Coffee'),
            new Todo('Write simpler code')
        ]), 1500)
    })
}

function fetchSomeUsers() {
    return new Promise(resolve => {
        setTimeout(() => resolve([
            {name: 'user1'},
            {name: 'user2'}
        ]), 1500)
    })
}

class TodoList {
    @force $: TodoList
    @mem set users(next: {name: string}[] | Error) {}
    @mem get users() {
        fetchSomeUsers()
           .then(users => { this.$.users = users })
           .catch(error => { this.$.users = error })
        throw new mem.Wait()
    }

    @mem set todos(next: Todo[] | Error) {}
    @mem get todos() {
        fetchSomeTodos()
           .then(todos => { this.$.todos = todos })
           .catch(error => { this.$.todos = error })
        throw new mem.Wait()
    }
    @mem get unfinishedTodoCount() {
        return this.todos.filter(todo => !todo.finished).length;
   ...