So you see these two goals are contradictory. How FP tackles this state problem? One solution is to use actors and agents. And that's precisely what elmish is. Unlike the conventional apps where you mutate the state directly, an agent in F# is a recursive call which can await for further messages.
So just like Flip Flop holds the state in memory, an agent hold the state in a recursive function. And how is this connected to elmish? Let's see how elmish v2 is implemented: https://github.com/elmish/elmish/blob/5330f52153d5181923bb3c... You can see an agent there and that's the core of elmish.
So basically elm and elmish is a way to handle state changes in a functional manner along with side effect support via commands.
I cannot emphasis importance of elmish, because not only it helps for isolating the state functionally but it helps you to keep your business logic separate from UI. So you don't end up messing your code like you use React hooks or context.