reactive-python/reactpy-router

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
  • 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 (formerly Switch)
    • 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 within browser_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)

There's some WIP docs here.

can the link be inserted into the button like this

html.button({
"to":"/about"
},"To about")

but not working or there is another way