Skip to content

ReactPyCsr

Overview

ReactPyCsr serves a page that runs your component code in the browser via PyScript. There is no websocket: the component renders entirely client-side.

from reactpy.executors.asgi import ReactPyCsr

my_app = ReactPyCsr("root.py", initial="Loading...")

Reference

ReactPyCsr(*file_paths, **settings)

from reactpy.executors.asgi import ReactPyCsr

Parameters

  • *file_paths: One or more paths to Python files containing components. Each is read at request time and its source is inlined into the served HTML. Accepts str or pathlib.Path.

  • root_name (optional): The name of the root component inside your Python file. Defaults to "root". The file may define any number of components; this one is mounted.

    ReactPyCsr("components.py", root_name="my_app")
    

    The name must match exactly, and the object must be a component.

  • initial (optional): Content shown while PyScript boots. A string or a VdomDict. Defaults to "".

  • extra_py (optional): Additional Python packages to install into the PyScript runtime, as version specifier strings.

  • extra_js (optional): Additional JavaScript modules, as a dict[str, str] where each key is the URL of the JavaScript file and the value is the name to export it as — {"/static/foo.js": "foo"}. The name is how the module is reached from the component, via pyscript.js_modules.foo. Same direction as the js_modules.main block PyScript itself consumes.

  • pyscript_config (optional): Raw PyScript configuration dictionary.

  • http_headers, html_head, prepend_body, html_lang: Same meaning as in ReactPy.

  • **settings: Any key from ReactPyConfig.

Returns

An ASGI application.


Usage

Files

Two files: the ASGI app, and the root component.

1
2
3
4
5
my_app = ReactPyCsr(
    Path(__file__).parent / "root.py",
    initial="Loading...",
    root_name="root",
)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from reactpy import component, html, use_state


@component
def root():
    count, set_count = use_state(0)
    return html.div(
        html.h1(count),
        html.button({"onClick": lambda event: set_count(count + 1)}, "Add 1"),
    )
1
# TODO

Serve with uvicorn main:my_app. The served page carries the Loading... placeholder, the PyScript bootstrap, and your component source.

Your component source is public

ReactPyCsr embeds the text of every file you pass into the HTML response, so the browser can execute it. Verified: requesting the index route returned the full body of the component file, including components that are not mounted.

Treat these files as client-side code. Do not read secrets, query a database, or call privileged APIs from a CSR component — anything reachable from that file is reachable by anyone who loads the page. CSR is for genuinely client-side work: offline apps, demos, UI that needs no server authority. For anything that touches data you do not publish, use ReactPy or ReactPyMiddleware, which keep your Python on the server.

How it loads

The page ReactPy generates does three things:

  1. Links PyScript's CSS and module script from {path_prefix}static/.
  2. Declares the packages to install, starting with ReactPy's own wheel and morphdom.
  3. Inlines your Python, then runs it under PyScript.

Verified against a running server: the initial response contains the PyScript core.js, the packages list pointing at the ReactPy wheel, and the initial placeholder inside a <div class="pyscript">.

The first load is slow

The browser downloads and installs a CPython runtime plus your packages before anything renders. That is what initial is for. pyscript_config and extra_py let you pin packages, and packages_cache controls re-download, but the cold start is inherent to running Python in the browser.

Choosing CSR over the other executors

Where your Python runs Needs a websocket Source visible to the client
ReactPy server yes no
ReactPyMiddleware server yes no
ReactPyCsr browser no yes

Pick CSR when the client must work without a server connection. Pick one of the others whenever the component touches anything you would not publish.

PyScript without CSR

ReactPy accepts pyscript_setup=True to load PyScript alongside server-rendered components, for mixed setups. ReactPyCsr is the fully client-side case.

Authors: Archmonger