Reactions
Reactions are similar to a computed value, but instead of producing a new value, a reaction produces a side effect for things like printing to the console, making network request, incrementally updating the React component tree to patch the DOM, etc. In short, reactions bridge reactive and imperative programming.
React Components
If you are using React, you can turn your (stateless function) components into reactive components by simply adding the observer
function / decorator from the mobx-react
package onto them.
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {observer} from 'mobx-react';
@observer
class TodoListView extends Component {
render() {
return <div>
<ul>
{this.props.todoList.todos.map(todo =>
<TodoView todo={todo} key={todo.id} />
)}
</ul>
Tasks left: {this.props.todoList.unfinishedTodoCount}
</div>
}
}
const TodoView = observer(({todo}) =>
<li>
<input
type="checkbox"
checked={todo.finished}
onClick={() => todo.finished = !todo.finished}
/>{todo.title}
</li>
)
const store = new TodoList();
ReactDOM.render(<TodoListView todoList={store} />, document.getElementById('mount'));
observer
turns React (function) components into derivations of the data they render. When using MobX there are no smart or dumb components. All components are rendered smartly but are defined in a dumb manner. MobX will simply make sure the components are always re-rendered whenever needed, but also no more than that. So the onClick
handler in the above example will force the proper TodoView
to render, and it will cause the TodoListView
to render if the number of unfinished tasks has changed. However, if you would remove the Tasks left
line (or put it into a separate component), the TodoListView
will no longer re-render when ticking a box.
Custom Reactions
Custom reactions can simply be created using the autorun
, reaction
, or when
functions to fit your specific situations.
For example, the following autorun
prints a log message each time the amount of unfinishedTodoCount
changes:
autorun(() => {
console.log("Tasks left: " + todos.unfinishedTodoCount)
})