URL Routing Support (SPA)
Archmonger opened this issue · 18 comments
Current Situation
Currently, URL routes cannot be resolved within IDOM.
Proposed Changes
Add support for URL routing within IDOM core.
Implementation Details
Add React-Router
into IDOM core.
Here an example on how this can be implemented
def route_component():
http.browser_router(
http.route("/"),
http.route("path_1/"),
http.route("path_2/")
)
And here's a reference video on explaining react-router.
Things to be implemented
BrowserRouter
- Top level location to signify "this part of the code contains routing"
Route
- This is where the actual URL path goes
- React Router uses some weird system for variables within URLs
- Instead of that, we can possibly support regex paths
- I'm a bit biased and I think django's URL route matching looks visually cleaner than regex though
- Can possibly accept a kwarg of
regex: bool = False
to allow for regex routes?
Link
- Clicking on the contents of this changes the browser URL, but does not perform a HTTP refresh on the page
- Basically just a href with
prevent_default
pre-applied - Should accept a kwarg of
regex: bool = False
to allow for regex links
useHistory
useLocation
useParams
useMatch
Things that might not need to be implemented
Routes
(formerlySwitch
)- In React, this is used to allow matching more than one potential path.
- In IDOM, this won't be needed if using a
match_all=False
kwarg withinbrowser_router
NavLink
- It's just a link with extra styling. Doesn't really matter.
Redirect
- Doesn't need to exist if we just tell the user to use a regular HREF to do a HTTP page load.
MemoryRouter
- Debug utility that isn't that important.
StaticRouter
- Used for server side rendering, which we don't have.
Prompt
- Just a pop-up asking whether you really want to navigate away from the page
- This is useful but is way lower priority
Examples have been added on potential styling patterns.
There's a very high chance we pick the react style, but just want to make sure options are listed.
I've updated this with a deep dive into what React-Router API endpoints need to be replicated for MVP URL routing support.
I've done a little bit of thinking on this here and there and at the moment I'm leaning towards the idea of making this a separate package (e.g. idom-router
). I'm also imagining that the implementation might rely on Web Components.
If it can be a separate package then it should be.
But need to consider whether the current infrastructure is flexible enough to support URL routing outside of core.
Agreed. Especially given this is how react does it. With that said, without charges to core I'm not sure how clean the implementation will be. Regardless, I'm thinking I hack a prototype and see how bad it is before I go making changes in core before I really groc how routing works.
I've created a draft implementation here: https://github.com/idom-team/idom-router
I would discourage using it until I've had the time to flesh it out with more tests and documentation. The interface is subject to change (I haven't looked too closely at how React Router does things yet). I'm mostly interested in getting some early feedback on the implementation or for interface suggestions. For the moment though, usage looks like:
from idom import component, html, run
from idom.backend import default
from idom_router.router import Route, Link, bind
Router = bind(default)
@component
def Sample():
return Router(
Route("/", Link({"id": "root"}, "to a", to="/a")),
Route("/a", Link({"id": "a"}, "to b", to="/b")),
Route("/b", Link({"id": "b"}, "to c", to="/c")),
Route("/c", Link({"id": "c"}, "to default", to="/default")),
Route("/*", html.h1({"id": "default"}, "Default")),
)
run(Sample)
Route patterns follow standard glob rules (see fnmatch
module for details) unless an re.Pattern
is provided.
Also, inside your routes, if you want to get the current location, you need to use use_location
from idom_router
. The use_location
hook from the backend implementation will always give you the location the user initially arrived at.
I'm not entirely sure what you're trying to do with the third and fourth positional arguments ("to a", to="/a"
) in Route
, but everything else about the overall design for Router
and Route
seems solid.
I would rename Router
to BrowserRouter
to be consistent with react-router
.
This issue should be transferred to idom-team/idom-router
Is this issue closable, since the initial package has been released?
Or are we keeping it open to track the development goals?
I think we can close this. Any features mentioned here that we should still implement can be created as separate issues.
Should we have a quick discussion on which of the "Things to be implemented" on this issue are worth moving forward with?
is there a complete example to do routing with reactpy_router and with navigation links
i get errror
root@miop-HP-Convertible-x360-11-ab1XX:/home/miop/belajar/reactpy-router# python3 main.py
Traceback (most recent call last):
File "/home/miop/belajar/reactpy-router/main.py", line 2, in <module>
import reactpy_router
File "/home/miop/belajar/reactpy-router/reactpy_router/__init__.py", line 4, in <module>
from . import simple
File "/home/miop/belajar/reactpy-router/reactpy_router/simple.py", line 9, in <module>
from reactpy_router.core import create_router
File "/home/miop/belajar/reactpy-router/reactpy_router/core.py", line 117, in <module>
module_from_file("reactpy-router", file=Path(__file__).parent / "bundle.js"),
File "/usr/local/lib/python3.10/dist-packages/reactpy/web/module.py", line 196, in module_from_file
raise FileNotFoundError(f"Source file does not exist: {source_file}")
from reactpy import component, html, run
from reactpy_router import Route, Link, bind
@component
def App():
return html.h1("Hello, world!")
run(App)
Are you running this using a developer installation? I don't get this error if I just pip install reactpy-router
.
i have installed with pip install reactpy-router . but when running it still error like that
info
root@miop-HP-Convertible-x360-11-ab1XX:/home/miop/belajar/reactpy-router# python3 --version
Python 3.10.6
now I have resolved the error by reinstalling the package . is there a way to use it up to router parameters, router queries, and more details
root@miop-HP-Convertible-x360-11-ab1XX:/home/miop/belajar/reactrouter-py# python3 main.py
Traceback (most recent call last):
File "/home/miop/belajar/reactrouter-py/main.py", line 3, in
from reactpy_router import Route, Link, bind
ImportError: cannot import name 'Link' from 'reactpy_router' (/usr/local/lib/python3.10/dist-packages/reactpy_router/init.py)
can the link be inserted into the button like this
html.button({
"to":"/about"
},"To about")
but not working or there is another way
Please start a discussion: https://github.com/reactive-python/reactpy-router/discussions