Last active
January 13, 2018 20:52
-
-
Save upvalue/041ea6f5e5c3d6feb86da7f3a33b593f to your computer and use it in GitHub Desktop.
TypeScript + React + mobx-state-tree
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as React from 'react'; | |
import * as ReactDOM from 'react-dom'; | |
import { computed, observable } from 'mobx'; | |
import { observer } from 'mobx-react'; | |
import { types } from 'mobx-state-tree'; | |
const Todo = types.model({ | |
text: types.string | |
}) | |
const Store = types.model({ | |
todos: types.array(Todo), | |
}).actions((self) => { | |
return { | |
// The typeof operator belo is the important one: this is how you interact with types introduced | |
// by mobx-state-tree | |
add (todo: typeof Todo.Type) { | |
self.todos.push(todo); | |
}, | |
remove(todo: typeof Todo.Type) { | |
// self.todos.remove(todo); | |
// This is necessary to interact with Store.Type.todos, which is an IObservable array, not | |
// a normal array, which is what filter returns. | |
self.todos.replace(self.todos.filter((v, i) => { | |
return v.text !== todo.text; | |
})); | |
}, | |
} | |
}); | |
@observer | |
class App extends React.Component<{store: typeof Store.Type}> { | |
todoInput: HTMLInputElement; | |
addTodo(e: React.SyntheticEvent<HTMLButtonElement>) { | |
e.preventDefault(); | |
if(this.todoInput.value !== '') { | |
this.props.store.add({ text: this.todoInput.value }); | |
// Notice that this is type-checked properly. For example, something like this: | |
// this.props.store.add({ tyxt: true }); | |
// Will result in a compile-time error | |
this.todoInput.value = ''; | |
} | |
} | |
removeTodo(e: React.SyntheticEvent<HTMLButtonElement>, todo: typeof Todo.Type) { | |
e.preventDefault(); | |
this.props.store.remove(todo); | |
} | |
render() { | |
return <div> | |
<form> | |
<input ref={(r) => { if(r) this.todoInput = r; }} type="text" placeholder="Add entry" /> | |
<button type="submit" onClick={(e) => this.addTodo(e)}>Add todo</button> | |
</form> | |
<ul> | |
{this.props.store.todos.map((item, i) => { | |
return <li key={i}> | |
{item.text} | |
<button onClick={(e) => this.removeTodo(e, item)}>Remove</button> | |
</li> | |
})} | |
</ul> | |
</div> | |
} | |
} | |
document.addEventListener('DOMContentLoaded', () => { | |
const store = Store.create({ todos: [] }); | |
ReactDOM.render(<App store={store} />, document.getElementById('root')); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment