The first step is to create a basic router that will display the home page when the user navigates to the root of the application, and a "missing link" page for any other route.
1 2 3 4 5 6 7 8 91011121314
fromreactpyimportcomponent,html,runfromreactpy_routerimportbrowser_router,route@componentdefroot():returnbrowser_router(route("/",html.h1("Home Page 🏠")),route("{404:any}",html.h1("Missing Link 🔗💥")),)run(root)
When navigating to http://127.0.0.1:8000 you should see Home Page 🏠. However, if you go to any other route you will instead see Missing Link 🔗💥.
With this foundation you can start adding more routes.
1 2 3 4 5 6 7 8 9101112131415
fromreactpyimportcomponent,html,runfromreactpy_routerimportbrowser_router,route@componentdefroot():returnbrowser_router(route("/",html.h1("Home Page 🏠")),route("/messages",html.h1("Messages 💬")),route("{404:any}",html.h1("Missing Link 🔗💥")),)run(root)
With this change you can now also go to /messages to see Messages 💬.
Instead of using the standard reactpy.html.a element to create links to different parts of your application, use reactpy_router.link instead. When users click links constructed using reactpy_router.link, ReactPy will handle the transition and prevent a full page reload.
1 2 3 4 5 6 7 8 91011121314151617181920212223
fromreactpyimportcomponent,html,runfromreactpy_routerimportbrowser_router,link,route@componentdefroot():returnbrowser_router(route("/",home()),route("/messages",html.h1("Messages 💬")),route("{404:any}",html.h1("Missing Link 🔗💥")),)@componentdefhome():returnhtml.div(html.h1("Home Page 🏠"),link({"to":"/messages"},"Messages"),)run(root)
Now, when you go to the home page, you can click Messages link to go to /messages.
importoperatorfromtypingimportTypedDictfromreactpyimportcomponent,html,runfromreactpy_routerimportbrowser_router,link,routemessage_data:list["MessageDataType"]=[{"id":1,"with":["Alice"],"from":None,"message":"Hello!"},{"id":2,"with":["Alice"],"from":"Alice","message":"How's it going?"},{"id":3,"with":["Alice"],"from":None,"message":"Good, you?"},{"id":4,"with":["Alice"],"from":"Alice","message":"Good, thanks!"},{"id":5,"with":["Alice","Bob"],"from":None,"message":"We meeting now?"},{"id":6,"with":["Alice","Bob"],"from":"Alice","message":"Not sure."},{"id":7,"with":["Alice","Bob"],"from":"Bob","message":"I'm here!"},{"id":8,"with":["Alice","Bob"],"from":None,"message":"Great!"},]@componentdefroot():returnbrowser_router(route("/",home()),route("/messages",all_messages(),# we'll improve upon these manually created routes in the next section...route("/with/Alice",messages_with("Alice")),route("/with/Alice-Bob",messages_with("Alice","Bob")),),route("{404:any}",html.h1("Missing Link 🔗💥")),)@componentdefhome():returnhtml.div(html.h1("Home Page 🏠"),link({"to":"/messages"},"Messages"),)@componentdefall_messages():last_messages={", ".join(msg["with"]):msgformsginsorted(message_data,key=operator.itemgetter("id"))}messages=[]formsginlast_messages.values():_link=link({"to":f"/messages/with/{'-'.join(msg['with'])}"},f"Conversation with: {', '.join(msg['with'])}",)msg_from=f"{''ifmsg['from']isNoneelse'🔴'}{msg['message']}"messages.append(html.li({"key":msg["id"]},html.p(_link),msg_from))returnhtml.div(html.h1("All Messages 💬"),html.ul(messages),)@componentdefmessages_with(*names):messages=[msgformsginmessage_dataiftuple(msg["with"])==names]returnhtml.div(html.h1(f"Messages with {', '.join(names)} 💬"),html.ul([html.li({"key":msg["id"]},f"{msg['from']or'You'}: {msg['message']}",)formsginmessages]),)run(root)MessageDataType=TypedDict("MessageDataType",{"id":int,"with":list[str],"from":str|None,"message":str},)
In the example above we had to manually create a messages_with(...) component for each conversation. This would be better accomplished by defining a single route that declares route parameters instead.
Any parameters that have matched in the currently displayed route can then be consumed with the use_params hook which returns a dictionary mapping the parameter names to their values. Note that parameters with a declared type will be converted to is in the parameters dictionary. So for example /my/route/{my_param:float} would match /my/route/3.14 and have a parameter dictionary of {"my_param":3.14}.
If we take this information and apply it to our growing example application we'd substitute the manually constructed /messages/with routes with a single /messages/with/{names} route.
importoperatorfromtypingimportTypedDictfromreactpyimportcomponent,html,runfromreactpy_routerimportbrowser_router,link,route,use_paramsmessage_data:list["MessageDataType"]=[{"id":1,"with":["Alice"],"from":None,"message":"Hello!"},{"id":2,"with":["Alice"],"from":"Alice","message":"How's it going?"},{"id":3,"with":["Alice"],"from":None,"message":"Good, you?"},{"id":4,"with":["Alice"],"from":"Alice","message":"Good, thanks!"},{"id":5,"with":["Alice","Bob"],"from":None,"message":"We meeting now?"},{"id":6,"with":["Alice","Bob"],"from":"Alice","message":"Not sure."},{"id":7,"with":["Alice","Bob"],"from":"Bob","message":"I'm here!"},{"id":8,"with":["Alice","Bob"],"from":None,"message":"Great!"},]@componentdefroot():returnbrowser_router(route("/",home()),route("/messages",all_messages(),route("/with/{names}",messages_with()),# note the path param),route("{404:any}",html.h1("Missing Link 🔗💥")),)@componentdefhome():returnhtml.div(html.h1("Home Page 🏠"),link({"to":"/messages"},"Messages"),)@componentdefall_messages():last_messages={", ".join(msg["with"]):msgformsginsorted(message_data,key=operator.itemgetter("id"))}messages=[]formsginlast_messages.values():msg_hyperlink=link({"to":f"/messages/with/{'-'.join(msg['with'])}"},f"Conversation with: {', '.join(msg['with'])}",)msg_from=f"{''ifmsg['from']isNoneelse'🔴'}{msg['message']}"messages.append(html.li({"key":msg["id"]},html.p(msg_hyperlink),msg_from))returnhtml.div(html.h1("All Messages 💬"),html.ul(messages),)@componentdefmessages_with():names=tuple(use_params()["names"].split("-"))# and here we use the path parammessages=[msgformsginmessage_dataiftuple(msg["with"])==names]returnhtml.div(html.h1(f"Messages with {', '.join(names)} 💬"),html.ul([html.li({"key":msg["id"]},f"{msg['from']or'You'}: {msg['message']}",)formsginmessages]),)run(root)MessageDataType=TypedDict("MessageDataType",{"id":int,"with":list[str],"from":str|None,"message":str},)