Router: Hash support for the web
Specific Demand
Right now the Router has no hash support for the web, which means that if the server does not redirect every request to the index.html file, a user visiting the /new route, without visiting the / route first, will be greeted by a 404 Error code.
Instead there should be the option to specify # as the route root, or maybe have a HashRouter for the web. This would allow single page operations.
| Using the current router | Using a hash router |
|---|---|
| / | /#/ |
| /new | /#/new |
| /posts/:id | /#/posts/:id |
Implement Suggestion
As far as I can tell, the router currently works using the history, but a hash change is not committed to history.
But one might be able to use the onhashchange callback to update the router.
And then either the current Link { to: "/#" } coult be used to change it, or there could be a method in the use_route hook to change the current route (would support navigation after e.g. a web request (without using web_sys::location::set_pathname())
I don't think it is that hard to implement and if I find the time I might write a stand alone library (no promises though)
Yes! I think this is important!
In this project: https://github.com/mrxiaozhuox/diogen I have write the hash-router by myself. This is an important feature!
Looks like a great starting point, but I guess we should be using the Context feature, so one would be able to do
rsx!(
HashRouter {
Route {},
Route {}
}
)
Unless I'm missing something (not sure why you chose Atoms over Context [I'm guessing the feature didn't exist at that point? Can't tell, this projects website/docs seem broken in a lot of places - still prefer dioxus over react])
EDIT: Fixed the formatting
If I or someone else implemented this feature, would it be merged into the current router or should the person write a separate library (e.g. dioxus-web-hashrouter).
If it is going to be merged, I probably would have to fork this repo to change the files I guess? Why is the router in the packages folder? I mean you guys could have separated all these modules into separate git repos, would have made small contributions a lot easier (although I see, that it would be harder to manage)
If I or someone else implemented this feature, would it be merged into the current router or should the person write a separate library (e.g. dioxus-web-hashrouter).
If it is going to be merged, I probably would have to fork this repo to change the files I guess? Why is the router in the packages folder? I mean you guys could have separated all these modules into separate git repos, would have made small contributions a lot easier (although I see, that it would be harder to manage)
If you have a PR to add this feature, it's will be merged to dioxus repo.
Small update
I've rewritten parts of the router service and replaced the old path based router with a HashRouter.
I also edited the route_matches_path function to allow for easier path comparison, by filtering out empty segments (e.g. //// is the same as /).
Disclaimer
I haven't finished implementing everything yet, which is why the code hasn't been cleaned up. I also haven't tested if the Router still works in the non-web version, but I plan on doing that before doing a PR.
Progress & Problems
As I stated above, not everything is working properly. I'm currently testing with an admin panel I'm working on, which is why I can't open source the testing repo, but it has a lot of different navigation techniques build in, so I'm able to find bugs.
| Route | does it work? / notes |
|---|---|
| / | works |
| /new | works |
| /c/:id | does not work: route_matches_path returns the correct value, but the element is not being rendered, no error is being thrown |
| Redirect {} | works |
| Link {} | seems to be broken, not sure though, might be my code |
Check my progress here
Future plans
I'm putting this on hold for a couple of days, because I want to write my own router implementation from the ground up, to be able to compare the two. I hope that this way I'm able to determine if an error is caused by my rust code or web assembly.
After finishing or stopping development of my own router, I plan on finishing the code to get a PR ready. I'm not sure if replacing the old web router entirely was a good idea, but that way I didn't have to add a router_type: WebRouterType option to the RouterCore.
As always I'll keep you updated
EDIT: Expanded Note for /c/:id route
May Update
I finished writing my own router implementation only to learn that nearly no std::sync feature is supported at the moment, which meant that I could not implement my Router into a component. This means that I probably wont continue working on this unless I find a way to work without Mutexs or thread safety is implemented.
EDIT: I noticed that the current router is using a futures-channel library - maybe I'll try that out in the future.
EDIT: Update
I finally got futures and cells figured out and am working on an alpha version now
I'm happy to announce that I was in fact successful in porting my router core to a system without using threads.
Introducing: Roux
And I'm finally able to release my own router: dioxus-roux.
In case you want to track the development of it, I host it over on codeberg.org as it is not meant to be merged (the router code bases are totally different).
Roux allows the user to add as many back-ends as they wish, and even specifying custom back-ends is possible. (Only a web hash back-end is available at the moment).
Conclusion
As I'll probably be working on my own router, I will probably not finish the PR anytime soon (I haven't worked on it since then, but the hash router is working in my dioxus fork). Which is why I think, that we should be closing this.
Since when this issue was opened, many things changed. I guess it's an important thing to bring back, given the newly written April 2023 dioxus router is still url based and hashes can't be used.
https://dioxuslabs.com/blog/release-040#enum-router
A hash router is partially implemented (but currently commented out) here