Handling changes in state
However, the preceding equation is only giving half the story of a UI. It's true that the visual representation is derived from the state (through the transformation function, fn), but it does not account for the user operations that occur on the UI. It's like we have completely ignored the user in the equation. After all, the interface is not just used to visually represent data (state), but to also allow the manipulation of that data.
This is where we need to introduce the concept of actions that represent these user operations, which results in a change in state. Actions are the commands that you invoke as a result of various input-events that are fired. These actions cause a change in the state, which is then reflected back on the UI.
We can visualize the triad of State, UI, and Actions in the following figure:
It is worth noting that the UI does not change the state directly, but instead does it via a message-passing system by firing actions. The action encapsulates the parameters that are required to cause the appropriate change in state. The UI is responsible for capturing various kinds of user events (clicks, keyboard presses, touches, voice, and so on) and translating them into one or more actions that are then fired to change the state.
When the State changes, it notifies all of its observers (subscribers) of the change. The UI is also one of the most important subscribers that is notified. When that happens, it re-renders and updates to the new state. This system of data flow from the State into the UI is always uni-directional and has become the cornerstone of state management in modern UI development.
One of the biggest benefits of this approach is that it becomes easy to grasp how the UI is kept in sync with changing data. It also cleanly separates the responsibilities between rendering and data changes. The React framework has really embraced this uni-directional data flow and you will see this adopted and extended in MobX as well.