DEV Community

Cover image for Intro to PYJSX
Debajyati Dey
Debajyati Dey

Posted on

Intro to PYJSX

Did you know that you can write JSX in python code?

Yes, I am not kidding! It is actually possible today!

You may have found jinja templates ugly and absolutely nightmare for templating in django or flask. If that's so, you are really going to enjoy this quick tutorial.

In this article, I am going to show you an interesting approach to component driven frontend development in python using a new library which is called pyjsx.

So, let's get started!

Get Started

Set up the Virtual Environment

First things first. Let's quickly set up a venv to install the required library.

python3 -m venv .venv
Enter fullscreen mode Exit fullscreen mode

and activate it -

In Linux/MacOS -

source .venv/bin/activate # for POSIX Shells
Enter fullscreen mode Exit fullscreen mode

In Windows -

./.venv/Scripts/activate.bat REM for windows cmd
Enter fullscreen mode Exit fullscreen mode
./.venv/Scripts/activate.ps1 # for powershell
Enter fullscreen mode Exit fullscreen mode

Install the Library

pyjsx logo

.venv/bin/pip3 install python-jsx # (for POSIX Shells)
Enter fullscreen mode Exit fullscreen mode
.\.venv\Scripts\pip3.exe install python-jsx # (for windows)
Enter fullscreen mode Exit fullscreen mode

If you use mypy then set up the ini file (mypy.ini) for accurate type checking.

[mypy]
plugins = pyjsx.mypy
Enter fullscreen mode Exit fullscreen mode

Now we are ready to dive in.

Note: I am not going to install flask or quart or hypercorn or any other dedicated backend framework or http server library, for this simple pyjsx demonstration.

We will use the http.server module from the standard library of python for setting up the web server.

Let's Write some Python JSX (PYJSX)

Just exactly how you write functional components and pass props to them in React you do it the same way in pyjsx.

for example, you would write a header component this way -

# coding: jsx
from pyjsx import jsx, JSX

def Header(style, children) -> JSX:
    return <h1 style={style}>{children}</h1>
Enter fullscreen mode Exit fullscreen mode

The most important things here to know and be careful about are -

  1. The comment # coding: jsx is REQUIRED. It is not a plain regular comment but a directive that tells Python to let our library parse the file first.
  2. The components can't be defined in a regular python file. You are only allowed to import the components in a python file, from the parsed files that contain the component definition(s). This component filename must end with .px file extension.
  3. The import from pyjsx import jsx is vital because PyJSX transpiles JSX into jsx(...) calls so it must be in scope.

Let's define some components

Make sure you put the file extension as .px NOT .py.

The <Header/> component -

# coding: jsx
from pyjsx import jsx, JSX

def Header(style, children) -> JSX:
    return <h1 style={style}>{children}</h1>
Enter fullscreen mode Exit fullscreen mode

The <Main/> component -

# coding: jsx
from pyjsx import jsx, JSX

def Main(children) -> JSX:
    return <main>{children}</main>
Enter fullscreen mode Exit fullscreen mode

And here is the <App/> component.

# coding: jsx
from pyjsx import jsx, JSX
from main import Main
from header import Header

def App() -> JSX:
    return (
        <div>
            <Header style={{"color": "darkgreen"}}>Hello from PYJSX!</Header>
            <Main>
                <p style={{"color": "crimson"}}>This was rendered with PyJSX!</p>
            </Main>
        </div>
    )
Enter fullscreen mode Exit fullscreen mode

Now, Here comes the part of server. We will set up a pretty simple http server to serve the <App/> component on GET request.

Hey, hey, hey, before writing a runnable file, remember this -

❗❗ To run a file containing JSX, the jsx codec must be registered first in the runtime, which can only be done with from pyjsx import auto_setup.
⚠️ This must occur before importing px files or any other file containing JSX.

Setting Up the server

Import modules -

from http.server import BaseHTTPRequestHandler, HTTPServer
from pyjsx import auto_setup # MUST import this before importing JSX
from app import App
Enter fullscreen mode Exit fullscreen mode

Define constants -

HOST = '127.0.0.1'
PORT = 8080
Enter fullscreen mode Exit fullscreen mode

Define the HTTP request handler class to setup server

class MyHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)

        # Send response headers
        self.send_header('Content-type', 'text/html')
        self.end_headers()

        # using fstring to convert the JSX into string
        response = f"{App()}"
        # convert the string data into bytes before sending over network
        self.wfile.write(response.encode())

    def log_message(self, format, *args):
        return  # Suppress default logging for clean output

def run_server():
    server = HTTPServer((HOST, PORT), MyHandler)
    print(f"Serving HTTP on {HOST}:{PORT} ...")
    try:
        server.serve_forever()
    except KeyboardInterrupt:
        print("\nShutting down the server.")
        server.server_close()
Enter fullscreen mode Exit fullscreen mode

Now let's run the server to see it in action (I mean browser).

Running the server through console

Look, our server works perfectly fine, and the pyjsx code is beautifully rendered in the DOM!
Rendered in browser

Look at the browser console -
elements in the browser console

Wrapping it up

You must be delighted to know that pyjsx also supports fragment components <></> and nested expressions like -

<div>
    {[<p>Row: {i}</p> for i in range(10)]}
</div>
Enter fullscreen mode Exit fullscreen mode

already.

So, we see that pyjsx has a lot of potential.

It is a new library, and I think it is not ready for production yet. But it is completely open source with Apache Licence, so with valuable community contributions we can make development of this library progress rapidly and see it as a huge leap forward towards declarative web ui development in python.

What do you think, want to give it a go?

Check it out in GitHub and explore more examples to build something awesome with it!

GitHub logo tomasr8 / pyjsx

Write JSX directly in Python

PyJSX - Write JSX directly in Python

PyPI - Version

from pyjsx import jsx, JSX

def Header(style, children) -> JSX:
    return <h1 style={style}>{children}</h1>

def Main(children) -> JSX:
    return <main>{children}</main>

def App() -> JSX:
    return (
        <div>
            <Header style={{"color": "red"}}>Hello, world!</Header>
            <Main>
                <p>This was rendered with PyJSX!</p>
            </Main>
        </div>
    )
Enter fullscreen mode Exit fullscreen mode

Installation

Get it via pip:

pip install python-jsx
Enter fullscreen mode Exit fullscreen mode

Minimal example (using the coding directive)

Tip

There are more examples available in the examples folder.

There are two supported ways to seamlessly integrate JSX into your codebase One…

Conclusion

I would really appreciate your feedback on this tutorial. How would you rate it? How can I improve it?

If you found this project or tutorial helpful, please consider sharing some love to the article. It will encourage me to create more content like this.

If you found this POST helpful, if this blog added some value to your time and energy, please support by sharing it with your developer friends.

Thanking you for Reading!

Follow me for more quality tech content. 👇🏽👇🏽👇🏽

Feel free to connect with me at - Twitter, LinkedIn or GitHub :)

Happy Coding 🧑🏽‍💻👩🏽‍💻! Have a nice day ahead! 🚀

Top comments (19)

Collapse
 
syedmuhammadaliraza profile image
Syed Muhammad Ali Raza

Insightful

Collapse
 
ddebajyati profile image
Debajyati Dey

Thanks for letting me know. Now build something cool with it

Collapse
 
mezieb profile image
Okoro chimezie bright

Cool thanks for sharing

Collapse
 
ddebajyati profile image
Debajyati Dey

You're welcome 🤗. Glad you found it useful 😁.

Collapse
 
subhro profile image
Subhradip Sinha

Insightful

Collapse
 
ddebajyati profile image
Debajyati Dey

Now build something cool with it

Collapse
 
parag_nandy_roy profile image
Parag Nandy Roy

That’s seriously cool ..

Collapse
 
ddebajyati profile image
Debajyati Dey

Yupp! It is a game changer!

Collapse
 
k0msenapati profile image
K Om Senapati

Wow its so cool

But is it better than Jinja2 ?
That can be setup easily with fastapi or flask

Collapse
 
ddebajyati profile image
Debajyati Dey • Edited

Well actually Jinja really serves its purpose greatly. That being said, it is a templating engine for python.

Jinja is generally static, (HTML rendered before delivery). While JSX is dynamic and is loved by devs mostly for its component-based reusability, nesting and the ability of easily passing props for dynamic behavior.

The best way is to use the best of both worlds. 

As in the end, we are converting PyJSX into strings currently for rendering as html, we will be able to use them directly in flask routes. What we can do is break our whole UI into reusable components and then serve them as html when sending via response in flask routes.

A Quick Example for you if my explanation above was messy (sorry 🥲😅😅🥲) -

PyJSX with Flask

With PyJSX, you define your components in Python files (often with a .px extension, though not strictly required for simple cases if transpiled correctly). The output of a PyJSX component is of JSX type which can be formatted in fstrings, which Flask can directly return.

First, define a PyJSX component. You would typically save this in a file, for example, component.px -

# coding: jsx
from pyjsx import jsx, JSX

def HomePage(user_name, items) -> JSX:
    list_items = [<li>{item}</li> for item in items]
    return (
        <>
            <h1>PyJSX Home Page</h1>
            <p>Welcome, {user_name} from PyJSX!</p>
            <p>Here are your items:</p>
            <ul>{list_items}</ul>
        </>
    )
Enter fullscreen mode Exit fullscreen mode

Then, in your Flask application (app.py), you would import and use these components:

from flask import Flask
from pyjsx import auto_setup
from component import HomePage

app = Flask(__name__)

@app.route('/')
def home_pyjsx():
    # Render the PyJSX component to a string
    rendered_html = HomePage(user_name="KOmSenpati", items=["Pen", "Paper", "Laptop"])
    print(rendered_html)
    return f'{rendered_html}', {'Content-Type': 'text/html'}

if __name__ == '__main__':
    app.run()
Enter fullscreen mode Exit fullscreen mode

See it works perfectly fine -

Running the flask server

Collapse
 
hawkaii profile image
Parthib Mukherjee

such a great blog. keep it up

Collapse
 
ddebajyati profile image
Debajyati Dey • Edited

Glad you found it interesting!

Collapse
 
drax_ profile image
fonbless mtohbless

Interesting..

Collapse
 
ddebajyati profile image
Debajyati Dey

Thanks now try it out and let me how it goes

Collapse
 
g_meteertrk_6e171c6889 profile image
G. Mete Ertürk

Collapse
 
ddebajyati profile image
Debajyati Dey

Why, do you hate python?

Collapse
 
g_meteertrk_6e171c6889 profile image
G. Mete Ertürk • Edited

No, I am even fine with people breaking established industry standards, I get it, it is fun. I just don't like it when people take the joke too seriously and actually start using these in production. Look what happened to React. They invent a new "solution" to the mess they helped create every year, and each solution requires two new inventions.

If you hold your ear from the other side so often that your arms get entangled, you should just let go.

Thread Thread
 
ddebajyati profile image
Debajyati Dey

Wow. insightful!

And the HeadWind HTML is super awesome man!! Lol!

Some comments may only be visible to logged-in visitors. Sign in to view all comments.