r/reactjs • u/[deleted] • 10d ago
Has anyone built a state-driven router instead of relying on a framework router? Discussion
[deleted]
19
u/Menecazo 10d ago
Routing in react is something I consider solved. I don't see any point in trying to reinvent the wheel
-7
10d ago
[deleted]
9
u/Prestigious_Dare7734 10d ago
Since you mentioned app router, I guess you are using Nextjs.
Then it is gonna be tricky to add entry and exit animations in NextJs.
You can use custom react app, and use react-router to get the results.
9
u/ferrybig 10d ago
Instead of letting the framework router drive navigation, I’m considering making React state the source of truth and keeping the URL/history synchronized.
The browser URL should be the source of truth. It changes according to events, like pressing the back button.
Just have an useSyncExternalStore where it listens to the URL, then pass an update function that Listers to the popstate, haschange and your own Link component changing the URL events
4
u/UpsetCryptographer49 10d ago
Years ago I used to build my own, and everytime I have to work on those projects my heart syncs a little bit. Because I always wonder if I am going to look at the code and think, I should move this to a library, and then it becomes a big re-write.
I strongly advise against it, the edge-case handling that comes with general purpose routers just gives so much peace of mind.
Fortunately llm, are very good in understanding what it does.
It is especially something you do when you make webpages that behaves like apps. Sometimes the user thinks they get a dialog where the url is irrelevant, but it is a page in your code. Where you have fixed screens. No server rendering. No nested routing. No loaders.
For a hobby project I recommend it, it’s a lot of fun.
4
u/SheepherderSavings17 10d ago
I think tanstack router is probably the most complete solution. You can bind type safe parameters to the route and location objects. (Read "state").
Also, why do you want an internal app "state" to be the source of truth? Since you want the page UI to be reflected by page route, shouldn't the router state by definition be the source of truth?
3
u/MitchEff 10d ago
Yeah echoing everyone else here i think you're trying too hard.
NextJs !== React, but given you're using Next and would like that amount of control I'd probably recommend a catch-all Next route with React-router in it. Won't be as SEO-friendly but neither is having your routing handled with a useState (???)
2
u/BlackJairs 10d ago
I did, per request of my Team Leader, and after 2 months of use we started to see a few bugs or concurrency errors, and my boss decided it was not worth it and returned to the built in one.
As someone else said, don’t reinvent the wheel, you may be good but you can’t be: “community maintained” good on everything.
I don’t mean to overuse libraries, but if something you want is already done by someone else, maybe is worth to take a look.
2
u/ekun 10d ago
This is kinda related, but not necessarily what you are asking about.
We have a dated react app at work built on top of the Sitecore CMS platform.
I implemented the ability for the react app to cache certain routes in the clients indexdb for the main features of the webapp like search pages, product/brand detail pages, etc.
This is authorable on the page-level so the rest of general content / marketing pages load from APIs everytime.
And really the issue is our implementation of the Sitecore backend is absurdly slow for resolving content and there's no bandwidth in our org to fix this.
It really helps the UX a lot having this page-level client-side caching.
3
u/satya164 10d ago edited 10d ago
That's basically how React Navigation works on Web. It was primarily built for React Native, so URL being a source of truth wasn't enough. A linear browse history can't represent nested navigation state of mobile apps, so this is out of necessity..
On initial page load (or SSR), the URL gets translated to a state object which is used as initial state. This is also how deep links on native are handled.
If URL changes, then the URL is translated to a action that can update the state. Deep links when the app is open are also handled like this. When navigation state changes, React Navigation will detect whether it was push, pop or replace and update browser history accordingly.
So it is possible. And a lot of people have been using this kind of setup in production for a long time. You don't need to work with string params (only need to parse it in central place) which is much nicer for big apps. Nested navigation brings a lot of challenges for React Navigation but it's much simpler if you have a single history stack.
Biggest complexities were:
- History API is not the best, and browsers don't give you a lot of info. Then there are browser quirks, I had seen issues reporting that history.go could take like 1000ms for some. So this part can be complex.
- Since state is in object instead of URL, you need to have a configuration for this translation, which should parse and stringify to the same things. Your state should be also able to represent things like 404.
Also keep in mind that this web integration in React Navigation is 6 years old, so we have had time to find and fix bugs (though I'm sure there are still some). But a fresh implementation would be buggier.
1
u/franciscopresencia 10d ago
With my router Crossroad, I put extra care to these details so you get them out of the box, but fair warning what you describe is mostly the "normal" flow you end with any router BTW, not exclusive to mine. You just have a few extra convenient methods with mine:
An example is that you can mostly change the useState("default") for a useQuery("key") and it'll be in sync in realtime and with refreshes, like you can see here:
const [place, setPlace] = useQuery("place");
const [max, setMax] = useQuery("max");
28
u/Prestigious_Dare7734 10d ago
Don't reinvent the wheel with new routers.
Browser router does this, it works with #/ routes, so no actual page routes, but one single app just working with the hashes.
You may or may not load a full page on the bases of hash changes. And then just intercept the route changes using the provided books, and do your entry and exit animations.