ReactPy: Empowering Dynamic Frontend Development with Python Magic

ReactPy: Empowering Dynamic Frontend Development with Python Magic

In the world of web development, ReactJS has emerged as a dominant player, offering developers a powerful toolset for creating dynamic and interactive user interfaces. However, what if you prefer the versatility and simplicity of Python for your backend, and wish to leverage its capabilities in the frontend as well? Enter ReactPy, a Python library that brings the familiar syntax and flexibility of ReactJS to the world of Python web development.

In this article, we will provide an overview of ReactPy and explore its features, benefits, and use cases. Whether you are a Python enthusiast looking to enhance your frontend skills or a developer seeking a seamless integration between your backend and frontend technologies, ReactPy can be a valuable addition to your toolkit. We will also guide you through the process of setting up ReactPy and demonstrate how to build a simple frontend application using this library.

What is ReactPy, basically.

Advantages and disadvantages of ReactPy

Advantages

  1. Familiarity: Many developers are already familiar with React. ReactPy provides a similar programming model and component-based architecture, allowing Python developers to leverage their existing knowledge and skills.
  2. Easy-to-Learn: ReactPy is also easy to learn and use, making it accessible to developers of all levels.
  3. Full-Stack Development: With ReactPy, developers can work on both the frontend and backend of their web applications using Python. This eliminates the need for switching between different programming languages and frameworks, providing a more seamless full-stack development experience.
  4. Community and Ecosystem: While ReactPy is relatively new (It was firstly released around 3 months ago), it benefits from the vibrant Python community and ecosystem. Developers can leverage existing Python libraries, tools, and frameworks to enhance their ReactPy projects, creating a more robust and scalable application. At the same time, you can google your problem in ReactJS, and then just change the code from JavaScript to Python.
  5. Easy to Install: If you have Python up and running already, installing ReactPy is really easy.
  6. Jupyter Notebooks: Some people may not agree with me, but I personally like to run my apps during development in Jupyter Notebooks sometimes. This allows running programs step-by-step, which makes it easier to debug and explain your program to others.
  7. Support for Other Python Backends: ReactPy supports Flask, FastAPI, Sanic, Tornado, Django, and many other libraries.

Disadvantages

  1. ReactPy is Relatively New: Since it was released not a long time ago, there are still some bugs, unfinished parts, documentation-in-progress, and small community.
  2. Python’s Asynchronous Limitations: Python’s asynchronous capabilities, particularly in versions prior to Python 3.7, may not align perfectly with ReactPy’s reactive programming model. This can make handling asynchronous operations, such as network requests, more challenging and require additional workarounds.
  3. Not All React Features are Done: Since ReactPy is still in development, not all React features are done and ready to use.
  4. Limited Popularity Among HRs and Companies: As ReactPy is a relatively new library, it may not be widely recognized or sought after by HRs and programmers in different IT companies. This means that job opportunities specifically targeting ReactPy development may be more limited compared to more established frontend technologies like ReactJS.

Getting Started with ReactPy

You will typically pip install ReactPy to alongside one of it’s natively supported backends. For example, if we want to run ReactPy using the Starlette backend you would run:

pip install "reactpy[starlette]"

Further parts of this article will be using ReactPy with Starlette backend. If you install other backends, I can’t guarantee that your code will run. 🙂

ReactPy includes built-in support for a variety backend implementations. If you need to, you can install more than one option by separating them with commas:

pip install "reactpy[fastapi,flask,sanic,starlette,tornado]"

If you want to install a “pure” version of ReactPy without a backend implementation you can do so without any installation extras. You might do this if you wanted to use a custom backend or if you wanted to manually pin the dependencies for your chosen backend:

pip install reactpy

Simple Frontend App Examples

Let’s start with a simple HelloWorld application. You can use Jupyter to run this code, or just usual Python Script:

# component for creating function that returns HTML-like React components, 
# html for website elements, 
# run for launching your app.
from reactpy import component, html, run 

# Define your component
@component
def HelloWorld():
    return html.h1("Hello, World!")

# Run it with a development server. For testing purposes only.
run(HelloWorld)

Your output should look like this:

2023-06-09T14:21:46+0200 | WARNING | The `run()` function is only intended for testing during development! To run in production, consider selecting a supported backend and importing its associated `configure()` function from `reactpy.backend.<package>` where `<package>` is one of ['starlette', 'fastapi', 'sanic', 'tornado', 'flask']. For details refer to the docs on how to run each package.
2023-06-09T14:21:46+0200 | INFO | Running with starlette.applications.Starlette at http://127.0.0.1:8000
INFO:     Started server process [12328]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     127.0.0.1:8274 - "GET / HTTP/1.1" 200 OK
INFO:     127.0.0.1:8274 - "GET /index.53b29c63.js HTTP/1.1" 200 OK
INFO:     ('127.0.0.1', 8276) - "WebSocket /_reactpy/stream" [accepted]
INFO:     connection open
INFO:     127.0.0.1:8274 - "GET /reactpy-logo.ico HTTP/1.1" 200 OK

Now, if you click the link http://127.0.0.1:8000, you will be able to see your first running ReactPy application:

Hello World!

By using Ctrl+C in Python console, you are able to close your application, and the website won’t be reachable any more. So, basically, whenever you want to make a component, you create a function that returns html and add a @componentdecorator.

Now, let’s do something more complicated. By using different HTML elements, you can add pictures, titles, captions, and put them all into one function:

from reactpy import component, html, run

@component
def Title(title):
    return html.h1(title)

# Load an image from https://picsum.photos/id/152/500/300,
# specify style of the image using CSS: width: 30%
@component
def Photo():
    return html.img(
        {
            "src": "https://picsum.photos/id/152/500/300",
            "style": {"width": "30%"},
        }
    )

@component
def PhotographerName(caption):
    return html.h4(caption)

# Combine all previous components in one function
@component
def PhotoViewer():
    return html.section(
        Title("Photo of the day"),
        Photo(),
        PhotographerName("Steven Spassov")
    )

run(PhotoViewer)

Result:

More components.

You can see that your code is reusable. So, for example, you can define a new function that has Photo and Photographer name, and after that use that function multiple times, specifying only url and name itself. This already is enough for making something like a gallery website.

Now, let’s add interactivity. After all, React is all about reacting to user’s actions. Let’s write some code:

from reactpy import component, html, run

# Define a function that return a button, which on clicking executes
# Python function "handle_event" (prints some text)
@component
def PrintButton(display_text, message_text):
    def handle_event(event):
        print(message_text)

    return html.button({"on_click": handle_event}, display_text)

@component
def App():
    return html.div(
        PrintButton("Play", "Playing"),
        PrintButton("Pause", "Paused"),
    )

run(App)

Your app will look like this:

We have buttons now.

When clicking Play, Python will print “Playing”, and for Pause button it will print “Paused”:

INFO:     ('127.0.0.1', 8385) - "WebSocket /_reactpy/stream" [accepted]
INFO:     connection open
INFO:     127.0.0.1:8383 - "GET /reactpy-logo.ico HTTP/1.1" 304 Not Modified
Playing
Paused

So, by using default HTML elements and ReactPy components, you can create Frontend apps with ease. For the final example let’s look at React’s states. React is not React without states, you know. Let’s take a look at this code:

import json
from pathlib import Path

from reactpy import component, hooks, html, run

# Define current script directory, save path to the data.json file in DATA_PATH,
# load this json file in sculpture_data (a dictionary)
HERE = Path(__file__)
DATA_PATH = HERE.parent / "data.json"
sculpture_data = json.loads(DATA_PATH.read_text())


@component
def Gallery():
    # Set React states
    index, set_index = hooks.use_state(0)
    
    # Function that will be ran after pressing the button.
    # It changes the index, so we can keep track of current state.
    def handle_click(event):
        set_index(index + 1)
    
    # Index shouldn't be bigger than amount of elements in data
    bounded_index = index % len(sculpture_data)
    # Take the data from dict
    sculpture = sculpture_data[bounded_index]
    alt = sculpture["alt"]
    artist = sculpture["artist"]
    description = sculpture["description"]
    name = sculpture["name"]
    url = sculpture["url"]

    return html.div(
        html.button({"on_click": handle_click}, "Next"),
        html.h2(name, " by ", artist),
        html.p(f"({bounded_index + 1} of {len(sculpture_data)})"),
        html.img({"src": url, "alt": alt, "style": {"height": "200px"}}),
        html.p(description),
    )


run(Gallery)

For running this code, you also need to create data.json file in the same directory as your Python script. Example of data:

[
  {
    "name": "Homenaje a la Neurocirugía",
    "artist": "Marta Colvin Andrade",
    "description": "Although Colvin is predominantly known for abstract themes that allude to pre-Hispanic symbols, this gigantic sculpture, an homage to neurosurgery, is one of her most recognizable public art pieces.",
    "url": "https://upload.wikimedia.org/wikipedia/commons/thumb/2/22/Homenaje_a_la_Neurocirug%C3%ADa%2C_Instituto_de_Neurocirug%C3%ADa%2C_Providencia%2C_Santiago_20200106_02.jpg/1024px-Homenaje_a_la_Neurocirug%C3%ADa%2C_Instituto_de_Neurocirug%C3%ADa%2C_Providencia%2C_Santiago_20200106_02.jpg",
    "alt": "A bronze statue of two crossed hands delicately holding a human brain in their fingertips."
  },
  {
    "name": "Eternal Presence",
    "artist": "John Woodrow Wilson",
    "description": "Wilson was known for his preoccupation with equality, social justice, as well as the essential and spiritual qualities of humankind. This massive (7ft. or 2,13m) bronze represents what he described as \"a symbolic Black presence infused with a sense of universal humanity.\"",
    "url": "https://upload.wikimedia.org/wikipedia/commons/6/6f/Chicago%2C_Illinois_Eternal_Silence1_crop.jpg",
    "alt": "The sculpture depicting a human head seems ever-present and solemn. It radiates calm and serenity."
  }
]

You can add more elements for getting more possible states in your website. After launching the app, you can get your interactive website with states:

Website that loads data from JSON and has a state that changes with clicking a button.

Conclusion

ReactPy is the Python library that brings ReactJS-like capabilities to frontend development with Python. With ReactPy, you can easily be a full-stack developer, taking care of both frontend and backend using the same language.

After this article you’ve learned basics of ReactPy, you can write simple frontend applications and understand how they work. Consult documentation and community resources for further guidance.

Unleash Python’s power in frontend development with ReactPy. Start experimenting, building modern user interfaces with ease. Happy coding!

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top