diff --git a/docs/examples/python/django_router.py b/docs/examples/python/django_router.py index e37ae0a8..721eb939 100644 --- a/docs/examples/python/django_router.py +++ b/docs/examples/python/django_router.py @@ -15,5 +15,5 @@ def my_component(): route("/router/string//", html.div("Example 6")), route("/router/uuid//", html.div("Example 7")), route("/router/two_values///", html.div("Example 8")), - route("/router/*", html.div("Fallback")), + route("/router/", html.div("Fallback")), ) diff --git a/docs/examples/python/use_mutation.py b/docs/examples/python/use_mutation.py index dcfabb3e..471a4a4c 100644 --- a/docs/examples/python/use_mutation.py +++ b/docs/examples/python/use_mutation.py @@ -25,6 +25,6 @@ def submit_event(event): return html.div( html.label("Add an item:"), - html.input({"type": "text", "on_key_down": submit_event}), + html.input({"type": "text", "onKeyDown": submit_event}), mutation_status, ) diff --git a/docs/examples/python/use_mutation_query_refetch.py b/docs/examples/python/use_mutation_query_refetch.py index 40d4100a..f2e014e9 100644 --- a/docs/examples/python/use_mutation_query_refetch.py +++ b/docs/examples/python/use_mutation_query_refetch.py @@ -39,7 +39,7 @@ def submit_event(event): return html.div( html.label("Add an item:"), - html.input({"type": "text", "on_key_down": submit_event}), + html.input({"type": "text", "onKeyDown": submit_event}), mutation_status, rendered_items, ) diff --git a/docs/examples/python/use_mutation_reset.py b/docs/examples/python/use_mutation_reset.py index 0b68d8b9..486f0464 100644 --- a/docs/examples/python/use_mutation_reset.py +++ b/docs/examples/python/use_mutation_reset.py @@ -22,12 +22,12 @@ def submit_event(event): if item_mutation.loading: mutation_status = html.h2("Adding...") elif item_mutation.error: - mutation_status = html.button({"on_click": reset_event}, "Error: Try again!") + mutation_status = html.button({"onClick": reset_event}, "Error: Try again!") else: mutation_status = html.h2("Mutation done.") return html.div( html.label("Add an item:"), - html.input({"type": "text", "on_key_down": submit_event}), + html.input({"type": "text", "onKeyDown": submit_event}), mutation_status, ) diff --git a/docs/examples/python/use_mutation_thread_sensitive.py b/docs/examples/python/use_mutation_thread_sensitive.py index 762b0819..2d047696 100644 --- a/docs/examples/python/use_mutation_thread_sensitive.py +++ b/docs/examples/python/use_mutation_thread_sensitive.py @@ -26,6 +26,6 @@ def submit_event(event): mutation_status = html.h2("Done.") return html.div( - html.input({"type": "text", "on_key_down": submit_event}), + html.input({"type": "text", "onKeyDown": submit_event}), mutation_status, ) diff --git a/docs/examples/python/use_query_refetch.py b/docs/examples/python/use_query_refetch.py new file mode 100644 index 00000000..c31c12c7 --- /dev/null +++ b/docs/examples/python/use_query_refetch.py @@ -0,0 +1,26 @@ +from channels.db import database_sync_to_async +from reactpy import component, html + +from example.models import TodoItem +from reactpy_django.hooks import use_query + + +async def get_items(): + return await database_sync_to_async(TodoItem.objects.all)() + + +@component +def todo_list(): + item_query = use_query(get_items) + + if item_query.loading: + rendered_items = html.h2("Loading...") + elif item_query.error or not item_query.data: + rendered_items = html.h2("Error when loading!") + else: + rendered_items = html.ul([html.li(item.text, key=item.pk) for item in item_query.data]) + + def on_click(event): + item_query.refetch() + + return html.div("Rendered items: ", rendered_items, html.button({"onClick": on_click}, "Refresh")) diff --git a/docs/examples/python/use_user_data.py b/docs/examples/python/use_user_data.py index 2c998db0..1526d6a8 100644 --- a/docs/examples/python/use_user_data.py +++ b/docs/examples/python/use_user_data.py @@ -16,5 +16,5 @@ def on_submit(event): html.div(f"Data: {query.data}"), html.div(f"Loading: {query.loading | mutation.loading}"), html.div(f"Error(s): {query.error} {mutation.error}"), - html.input({"on_key_press": on_submit}), + html.input({"onKeyPress": on_submit}), ) diff --git a/docs/src/reference/hooks.md b/docs/src/reference/hooks.md index 45a77602..b29990d5 100644 --- a/docs/src/reference/hooks.md +++ b/docs/src/reference/hooks.md @@ -135,22 +135,16 @@ Query functions can be sync or async. {% include-markdown "../../includes/orm.md" start="" end="" %} -??? question "Can I make a failed query try again?" +??? question "Can I force a query to run again?" - Yes, `#!python use_mutation` can be re-executed by calling `#!python reset()` on your `#!python use_mutation` instance. + `#!python use_query` can be re-executed by calling `#!python refetch()` on your `#!python use_query` result. - For example, take a look at `#!python reset_event` below. + The example below uses an `#!python onClick` event to determine when to reset the query. === "components.py" ```python - {% include "../../examples/python/use_mutation_reset.py" %} - ``` - - === "models.py" - - ```python - {% include "../../examples/python/todo_item_model.py" %} + {% include "../../examples/python/use_query_refetch.py" %} ``` ??? question "Why does the example query function return `#!python TodoItem.objects.all()`?" @@ -231,9 +225,9 @@ Mutation functions can be sync or async. {% include-markdown "../../includes/orm.md" start="" end="" %} -??? question "Can I make a failed mutation try again?" +??? question "Can I force a mutation run again?" - Yes, `#!python use_mutation` can be re-executed by calling `#!python reset()` on your `#!python use_mutation` instance. + `#!python use_mutation` can be re-executed by calling `#!python reset()` on your `#!python use_mutation` result. For example, take a look at `#!python reset_event` below. @@ -251,7 +245,7 @@ Mutation functions can be sync or async. ??? question "Can `#!python use_mutation` trigger a refetch of `#!python use_query`?" - Yes, `#!python use_mutation` can queue a refetch of a `#!python use_query` via the `#!python refetch=...` argument. + `#!python use_mutation` can queue a refetch of a `#!python use_query` via the `#!python refetch=...` argument. The example below is a merge of the `#!python use_query` and `#!python use_mutation` examples above with the addition of a `#!python use_mutation(refetch=...)` argument. diff --git a/docs/src/reference/router.md b/docs/src/reference/router.md index 757981f6..0d23ee99 100644 --- a/docs/src/reference/router.md +++ b/docs/src/reference/router.md @@ -25,9 +25,7 @@ URL router that enables the ability to conditionally render other components bas You can duplicate all your URL patterns within both Django and ReactPy, but it's easiest to use a wildcard `.*` within Django's `#!python urlpatterns` and let ReactPy handle the rest. For example... ```python linenums="0" - urlpatterns = [ - re_path(r"^.*$", my_reactpy_router_view), - ] + urlpatterns = [ re_path(r"^.*$", my_reactpy_router_view) ] ``` === "components.py" diff --git a/tests/test_app/components.py b/tests/test_app/components.py index b2f075f3..c505b3f6 100644 --- a/tests/test_app/components.py +++ b/tests/test_app/components.py @@ -38,7 +38,7 @@ def button(): html.div( "button:", html.button( - {"id": "counter-inc", "on_click": lambda _: set_count(count + 1)}, + {"id": "counter-inc", "onClick": lambda _: set_count(count + 1)}, "Click me!", ), html.p({"id": "counter-num", "data-count": count}, f"Current count is: {count}"), @@ -293,7 +293,7 @@ def _render_todo_items(items, toggle_item): "id": f"todo-item-{item.text}-checkbox", "type": "checkbox", "checked": item.done, - "on_change": lambda _, i=item: toggle_item(i), + "onChange": lambda _, i=item: toggle_item(i), }), ) for item in items @@ -342,8 +342,8 @@ def on_change(event): "type": "text", "id": "todo-input", "value": input_value, - "on_key_press": on_submit, - "on_change": on_change, + "onKeyPress": on_submit, + "onChange": on_change, }), mutation_status, rendered_items, @@ -413,8 +413,8 @@ async def on_change(event): "type": "text", "id": "async-todo-input", "value": input_value, - "on_key_press": on_submit, - "on_change": on_change, + "onKeyPress": on_submit, + "onChange": on_change, }), mutation_status, rendered_items, @@ -508,7 +508,7 @@ def on_click(_): html.button( { "id": f"{inspect.currentframe().f_code.co_name}_btn", - "on_click": on_click, + "onClick": on_click, }, "Click me", ), @@ -527,7 +527,7 @@ def on_click(_): html.button( { "id": f"{inspect.currentframe().f_code.co_name}_btn", - "on_click": on_click, + "onClick": on_click, }, "Click me", ), @@ -546,7 +546,7 @@ def on_click(_): html.button( { "id": f"{inspect.currentframe().f_code.co_name}_btn", - "on_click": on_click, + "onClick": on_click, }, "Click me", ), @@ -561,7 +561,7 @@ def custom_host(number=0): return html.div( { - "class_name": f"{inspect.currentframe().f_code.co_name}-{number}", + "className": f"{inspect.currentframe().f_code.co_name}-{number}", "data-port": port, }, f"Server Port: {port}", @@ -630,15 +630,15 @@ async def on_submit(event): "data-username": ("AnonymousUser" if current_user.is_anonymous else current_user.username), }, html.div("use_user_data"), - html.button({"className": "login-1", "on_click": login_user1}, "Login 1"), - html.button({"className": "login-2", "on_click": login_user2}, "Login 2"), - html.button({"className": "logout", "on_click": logout_user}, "Logout"), - html.button({"className": "clear", "on_click": clear_data}, "Clear Data"), + html.button({"className": "login-1", "onClick": login_user1}, "Login 1"), + html.button({"className": "login-2", "onClick": login_user2}, "Login 2"), + html.button({"className": "logout", "onClick": logout_user}, "Logout"), + html.button({"className": "clear", "onClick": clear_data}, "Clear Data"), html.div(f"User: {current_user}"), html.div(f"Data: {user_data_query.data}"), html.div(f"Data State: (loading={user_data_query.loading}, error={user_data_query.error})"), html.div(f"Mutation State: (loading={user_data_mutation.loading}, error={user_data_mutation.error})"), - html.div(html.input({"on_key_press": on_submit, "placeholder": "Type here to add data"})), + html.div(html.input({"onKeyPress": on_submit, "placeholder": "Type here to add data"})), ) @@ -685,13 +685,13 @@ async def on_submit(event): "data-username": ("AnonymousUser" if current_user.is_anonymous else current_user.username), }, html.div("use_user_data_with_default"), - html.button({"className": "login-3", "on_click": login_user3}, "Login 3"), - html.button({"className": "clear", "on_click": clear_data}, "Clear Data"), + html.button({"className": "login-3", "onClick": login_user3}, "Login 3"), + html.button({"className": "clear", "onClick": clear_data}, "Clear Data"), html.div(f"User: {current_user}"), html.div(f"Data: {user_data_query.data}"), html.div(f"Data State: (loading={user_data_query.loading}, error={user_data_query.error})"), html.div(f"Mutation State: (loading={user_data_mutation.loading}, error={user_data_mutation.error})"), - html.div(html.input({"on_key_press": on_submit, "placeholder": "Type here to add data"})), + html.div(html.input({"onKeyPress": on_submit, "placeholder": "Type here to add data"})), ) @@ -720,9 +720,9 @@ async def disconnect(event): }, html.div("use_auth"), html.div(f"UUID: {uuid}"), - html.button({"className": "login", "on_click": login_user}, "Login"), - html.button({"className": "logout", "on_click": logout_user}, "Logout"), - html.button({"className": "disconnect", "on_click": disconnect}, "disconnect"), + html.button({"className": "login", "onClick": login_user}, "Login"), + html.button({"className": "logout", "onClick": logout_user}, "Logout"), + html.button({"className": "disconnect", "onClick": disconnect}, "disconnect"), html.div(f"User: {current_user}"), ) @@ -752,9 +752,9 @@ async def disconnect(event): }, html.div("use_auth_no_rerender"), html.div(f"UUID: {uuid}"), - html.button({"className": "login", "on_click": login_user}, "Login"), - html.button({"className": "logout", "on_click": logout_user}, "Logout"), - html.button({"className": "disconnect", "on_click": disconnect}, "disconnect"), + html.button({"className": "login", "onClick": login_user}, "Login"), + html.button({"className": "logout", "onClick": logout_user}, "Logout"), + html.button({"className": "disconnect", "onClick": disconnect}, "disconnect"), html.div(f"User: {current_user}"), ) @@ -774,5 +774,5 @@ def on_click(event): }, html.div("use_rerender"), html.div(f"UUID: {uuid}"), - html.button({"on_click": on_click}, "Rerender"), + html.button({"onClick": on_click}, "Rerender"), ) diff --git a/tests/test_app/performance/components.py b/tests/test_app/performance/components.py index 54dd2280..1961fd40 100644 --- a/tests/test_app/performance/components.py +++ b/tests/test_app/performance/components.py @@ -17,7 +17,7 @@ def run_tests(): return html.div( html.div(f"Total renders: {count}"), html.div( - {"class_name": "rps", "data-rps": rps}, + {"className": "rps", "data-rps": rps}, f"Renders Per Second: {rps}", ), ) @@ -25,7 +25,7 @@ def run_tests(): @component def time_to_load(): - return html.div({"class_name": "ttl"}, "Loaded!") + return html.div({"className": "ttl"}, "Loaded!") GIANT_STR_10MB = "@" * 10000000 @@ -34,7 +34,7 @@ def time_to_load(): @component def net_io_time_to_load(): return html.div( - {"class_name": "ttl"}, + {"className": "ttl"}, html.div({"style": {"display": "none"}}, GIANT_STR_10MB), html.div("Loaded!"), ) @@ -59,7 +59,7 @@ def run_tests(): html.div({"style": {"display": "none"}}, GIANT_STR_1MB), html.div(f"Total renders: {count}"), html.div( - {"class_name": "rps", "data-rps": rps}, + {"className": "rps", "data-rps": rps}, f"Renders Per Second: {rps}", ), ) @@ -79,14 +79,14 @@ async def event_handler(event): return html.div( html.div(f"Total events: {count}"), html.div( - {"class_name": "erps", "data-erps": erps}, + {"className": "erps", "data-erps": erps}, f"Event Renders Per Second: {erps}", ), html.input({ "type": "text", - "default_value": "0", + "defaultValue": "0", "data-count": str(count), - "on_click": event_handler, + "onClick": event_handler, }), ) @@ -101,12 +101,12 @@ async def event_handler(_event): return html.div( html.input( { - "class_name": "et", + "className": "et", "data-clicked": clicked, "data-worker-num": worker_num, "value": f"Clicked: {clicked}", "type": "button", - "on_click": event_handler, + "onClick": event_handler, }, ), ) diff --git a/tests/test_app/pyscript/components/child.py b/tests/test_app/pyscript/components/child.py index 0ef5b3fb..43a243ea 100644 --- a/tests/test_app/pyscript/components/child.py +++ b/tests/test_app/pyscript/components/child.py @@ -10,11 +10,11 @@ def root(): html.div( {"className": "grid"}, html.button( - {"className": "plus", "on_click": lambda _: set_value(value + 1)}, + {"className": "plus", "onClick": lambda _: set_value(value + 1)}, "+", ), html.button( - {"className": "minus", "on_click": lambda _: set_value(value - 1)}, + {"className": "minus", "onClick": lambda _: set_value(value - 1)}, "-", ), ), diff --git a/tests/test_app/pyscript/components/counter.py b/tests/test_app/pyscript/components/counter.py index b8041057..2ce4379d 100644 --- a/tests/test_app/pyscript/components/counter.py +++ b/tests/test_app/pyscript/components/counter.py @@ -9,11 +9,11 @@ def root(): html.div( {"className": "grid"}, html.button( - {"className": "plus", "on_click": lambda _: set_value(value + 1)}, + {"className": "plus", "onClick": lambda _: set_value(value + 1)}, "+", ), html.button( - {"className": "minus", "on_click": lambda _: set_value(value - 1)}, + {"className": "minus", "onClick": lambda _: set_value(value - 1)}, "-", ), ),