As often, a quick change become a bigger one. I migrated number.oertel.fr from vercel to Cloudflare Worker because Cloudflare announced a way to host remix (and other frameworks) on a worker versus hosting in through Cloudflare Pages.
This project is the perfect use case for a SPA since there is no server side logic. Remix doesn’t support SPA just yet but they did add clientLoader/clientAction since I started.
The project requires to keep track a few states:
- current number to guess
 - submission count because the flow requires you to press “Enter” twice: once to validate your guess, and then once more to go to the next number.
 - status of the answer: correct or wrong
 - localStorage data to show your history at the bottom of the page
 - upper limit to the guessing domain
 - language (french or spanish)
 - method how to guess the number: read it and/or listen to it
 
with useState
Without clientLoader there is logic a bit everywhere:
- before the render, in 
useEffect, inline functions, etc. - in event handlers
 - when rendering the components
 - search parameters management on all input changes
 
Now with clientLoader
It allows to keep a nice separation of concerns between logic and presentation (I guess good old MVC but my model is kind of insignifiant).
Inside clientLoader I can now:
- check and parse query parameters
 - fetch 
localStoragedata - logic to check the guess
 
And in the render, I can rely on HTML inputs and form to track data. With clientLoader and Form (and the absence of server loader/action), there is no requests (POST or GET) done to the server.
I could have probably do a better job on the first version to rely less on useState but clientLoader gives the power of dealing of form submission without preventing the default behavior.
Checkout for yourself: version with useState vs. version with clientLoader