Globals are bad in general. Things should be as specific as they can be. If you were playing a tetris game and suddenly wanted to upgrade it and make it a DUALING side-by-side tetris game, then all your state is going to collide. It would have been better to define your <Tetris> tag to have it's own state.
It goes further than that, but essentially it's all about maintaining a context for a thing. I have a patient, that has meds and records etc, I need to keep that contained to one place so that I can have a SECOND patient at the same time (if I am writing an EHR for example). The original "UI of the web" was Open a thing, edit a thing, save and close a thing. And all of that was like 6 full page refreshes.
More apps should be like Trello, for example, where you can just edit a lot of state on lots of different objects super quickly. Globals don't work well for that.
I’m not convinced that this argument holds for the specific case of “a single global source of truth, with a structured and enforced update mechanism.”
Let’s expand your <Tetris> example. You didn’t specify whether both players are on the same computer or not. I agree that my <Tetris> instance should not depend on or conflict with any other player’s <Tetris> instance. What does that look like in practice?
Whether it’s local or internet play, we need a way to isolate each player’s game state. Each <Tetris> instance should only be concerned with displaying a single game state, and responding to at most one player’s inputs. What happens outside of that is not its concern: things like maybe logging into a server, knowing that there is a second <Tetris> instance running alongside it, knowing where garbage blocks came from, maybe knowing that my friends are online, etc.
To me, the obvious choice is to use something like
<Tetris state={app.player[0].gameState} />
If this is local multiplayer, there could be another <Tetris state={app.player[1].gameState} /> which has different input bindings. If it’s internet play, it could look the same and not have anything bound to inputs.
In either case, <Tetris> knows nothing about where its state comes from or goes to. But that state has to live somewhere for the app to access it, so where is it stored?
It goes further than that, but essentially it's all about maintaining a context for a thing. I have a patient, that has meds and records etc, I need to keep that contained to one place so that I can have a SECOND patient at the same time (if I am writing an EHR for example). The original "UI of the web" was Open a thing, edit a thing, save and close a thing. And all of that was like 6 full page refreshes.
More apps should be like Trello, for example, where you can just edit a lot of state on lots of different objects super quickly. Globals don't work well for that.