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)
    })
}

class TodoList {
    @force $: TodoList
    @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;
    }
}

function TodoListView({todoList}) {
  return <div>
    <ul>
      {todoList.todos.map(todo => 
         <TodoView todo={todo} key={todo.id} />
      )}
    </ul>
    Tasks left: {todoList.unfinishedTodoCount}
  </div>
}

function TodoListErrorableView({error}: Error) {
  return <div>{error instanceof mem.Wait ? 'pending...' : error.message}</div>
}

TodoListView.onError = TodoListErrorableView

function TodoView({todo}) {
 ...