Simple Counter App

Source Code

import js import asyncio from reactpy import html, component, use_state from reactpy.core.layout import Layout from jsonpointer import set_pointer from pyodide.ffi.wrappers import add_event_listener # --- Application Code --------------------------------------------------------- @component def app(): value, set_value = use_state(0) return html.article( html.div( {"class": "grid"}, html.button({"on_click": lambda event: set_value(value + 1)}, "+"), html.button({"on_click": lambda event: set_value(value - 1)}, "-"), ), "Current value", html.pre({"style": {"font-style": "bold"}}, str(value)), ) # --- Framework Code --------------------------------------------------------- model = {} def apply_update(update): if update["path"]: set_pointer(model, update["path"], update["model"]) else: model.update(update["model"]) def render_model(layout, model): root = js.document.getElementById("root") root.innerHTML = "" _render_model(layout, root, model) def _render_model(layout, parent, model): if isinstance(model, str): parent.appendChild(js.document.createTextNode(model)) elif isinstance(model, dict): if not model["tagName"]: for child in model.get("children", []): _render_model(layout, parent, child) return tag = model["tagName"] attributes = model.get("attributes", {}) children = model.get("children", []) element = js.document.createElement(tag) for key, value in attributes.items(): if key == "style": for style_key, style_value in value.items(): setattr(element.style, style_key, style_value) else: element.setAttribute(key, value) for event_name, event_handler_model in model.get("eventHandlers", {}).items(): _create_event_handler(layout, element, event_name, event_handler_model) for child in children: _render_model(layout, element, child) parent.appendChild(element) else: raise ValueError(f"Unknown model type: {type(model)}") def _create_event_handler(layout, element, event_name, event_handler_model): target = event_handler_model["target"] def event_handler(*args): asyncio.create_task(layout.deliver({ "type": "layout-event", "target": target, "data": args, })) event_name = event_name.lstrip("on_").lower().replace("_", "") add_event_listener(element, event_name, event_handler) async def main(): async with Layout(app()) as layout: while True: update = await layout.render() apply_update(update) render_model(layout, model) asyncio.create_task(main())
packages = ["reactpy", "ssl", "jsonpointer"] [splashscreen] enabled = false import js import asyncio from reactpy import html, component, use_state from reactpy.core.layout import Layout from jsonpointer import set_pointer from pyodide.ffi.wrappers import add_event_listener # --- Application Code --------------------------------------------------------- @component def app(): value, set_value = use_state(0) return html.article( html.div( {"class": "grid"}, html.button({"on_click": lambda event: set_value(value + 1)}, "+"), html.button({"on_click": lambda event: set_value(value - 1)}, "-"), ), "Current value", html.pre({"style": {"font-style": "bold"}}, str(value)), ) # --- Framework Code --------------------------------------------------------- model = {} def apply_update(update): if update["path"]: set_pointer(model, update["path"], update["model"]) else: model.update(update["model"]) def render_model(layout, model): root = js.document.getElementById("root") root.innerHTML = "" _render_model(layout, root, model) def _render_model(layout, parent, model): if isinstance(model, str): parent.appendChild(js.document.createTextNode(model)) elif isinstance(model, dict): if not model["tagName"]: for child in model.get("children", []): _render_model(layout, parent, child) return tag = model["tagName"] attributes = model.get("attributes", {}) children = model.get("children", []) element = js.document.createElement(tag) for key, value in attributes.items(): if key == "style": for style_key, style_value in value.items(): setattr(element.style, style_key, style_value) else: element.setAttribute(key, value) for event_name, event_handler_model in model.get("eventHandlers", {}).items(): _create_event_handler(layout, element, event_name, event_handler_model) for child in children: _render_model(layout, element, child) parent.appendChild(element) else: raise ValueError(f"Unknown model type: {type(model)}") def _create_event_handler(layout, element, event_name, event_handler_model): target = event_handler_model["target"] def event_handler(*args): asyncio.create_task(layout.deliver({ "type": "layout-event", "target": target, "data": args, })) event_name = event_name.lstrip("on_").lower().replace("_", "") add_event_listener(element, event_name, event_handler) async def main(): async with Layout(app()) as layout: while True: update = await layout.render() apply_update(update) render_model(layout, model) asyncio.create_task(main())