We've also referred to this as a reconciliation loop
Current state vs. desired state - moves things to the desired state.
This loop is used by everything. No new logic needs to be introduced to handle new use cases (for example, deletion is just remove one from the desired state, then this reconciliation loop takes care of it.)
A solution to this is that instead of returning a new state object, each component could return a piece of data representing a desired state change.
At 21 talks about the concept of a control-loop. Where you attempt to get to the desired state over and over.
Optimization can come from edge triggering, but you need to have level triggering stack-overflow-level-triggering-vs-edge-triggering. In other words, full reconciliation must eventually happen, but if you can do it based on a timely event, then that's a great optimization.
From the hacker news comments: "An event based system with a reliable event log becomes something that you can do a resync on. Which makes it into a pull based system in time of need."