There is a good reason: it becomes much easier to think about state transitions, because optimistic and “verified” updates both follow the same code path.
I've built a turn-based game that worked this way, where essentially every player and the server contains a copy of the same state machine, and the server determines the order of state updates. Like OP said, once you have the framework in place, it's magic.
It's over-engineered unless done properly, it which case it becomes a detail. I wouldn't be surprised to see some automatic conversion of server-side code to front-end by LiveView in the future for events where this behaviour is applicable, actually!
I've built a turn-based game that worked this way, where essentially every player and the server contains a copy of the same state machine, and the server determines the order of state updates. Like OP said, once you have the framework in place, it's magic.