Skip to content

Components

Overview

We supply some pre-designed that components can be used to help simplify development.


View To Component

Automatically convert a Django view into a component.

At this time, this works best with static views with no interactivity.

Compatible with sync or async Function Based Views and Class Based Views.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from reactpy import component, html
from reactpy_django.components import view_to_component

from . import views

hello_world_component = view_to_component(views.hello_world)


@component
def my_component():
    return html.div(
        hello_world_component(),
    )
1
2
3
4
5
from django.http import HttpResponse


def hello_world(request):
    return HttpResponse("Hello World!")
See Interface

Parameters

Name Type Description Default
view Callable | View | str The view to convert, or the view's dotted path as a string. N/A
transforms Sequence[Callable[[VdomDict], Any]] A list of functions that transforms the newly generated VDOM. The functions will be called on each VDOM node. tuple
strict_parsing bool If True, an exception will be generated if the HTML does not perfectly adhere to HTML5. True

Returns

Type Description
constructor A function that takes request, *args, key, **kwargs and returns a ReactPy component. Note that *args and **kwargs are directly provided to your view.
Existing limitations

There are currently several limitations of using view_to_component that may be resolved in a future version.

  • Requires manual intervention to change HTTP methods to anything other than GET.
  • ReactPy events cannot conveniently be attached to converted view HTML.
  • Has no option to automatically intercept local anchor link (such as <a href='example/'></a>) click events.
How do I use this for Class Based Views?

Class Based Views are accepted by view_to_component as an argument.

Calling as_view() is optional, but recommended.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from reactpy import component, html
from reactpy_django.components import view_to_component

from . import views

hello_world_component = view_to_component(views.HelloWorld.as_view())


@component
def my_component():
    return html.div(
        hello_world_component(),
    )
1
2
3
4
5
6
7
from django.http import HttpResponse
from django.views import View


class HelloWorld(View):
    def get(self, request):
        return HttpResponse("Hello World!")
How do I provide request, args, and kwargs to a converted view?

This component accepts request, *args, and **kwargs arguments, which are sent to your provided view.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from django.http import HttpRequest
from reactpy import component, html
from reactpy_django.components import view_to_component

from . import views

hello_world_component = view_to_component(views.hello_world)


@component
def my_component():
    request = HttpRequest()
    request.method = "GET"

    return html.div(
        hello_world_component(
            request,  # This request object is optional.
            "value_1",
            "value_2",
            kwarg1="abc",
            kwarg2="123",
        ),
    )
1
2
3
4
5
from django.http import HttpResponse


def hello_world(request, arg1, arg2, kwarg1=None, kwarg2=None):
    return HttpResponse(f"Hello World! {arg1} {arg2} {kwarg1} {kwarg2}")
How do I customize this component's behavior?

This component accepts arguments that can be used to customize its behavior.

Below are all the arguments that can be used.


strict_parsing

By default, an exception will be generated if your view's HTML does not perfectly adhere to HTML5.

However, there are some circumstances where you may not have control over the original HTML, so you may be unable to fix it. Or you may be relying on non-standard HTML tags such as <my-tag> Hello World </my-tag>.

In these scenarios, you may want to rely on best-fit parsing by setting the strict_parsing parameter to False. This uses libxml2 recovery algorithm, which is designed to be similar to how web browsers would attempt to parse non-standard or broken HTML.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from reactpy import component, html
from reactpy_django.components import view_to_component

from . import views

hello_world_component = view_to_component(views.hello_world)


@component
def my_component():
    return html.div(
        hello_world_component(),
    )
1
2
3
4
5
from django.http import HttpResponse


def hello_world(request):
    return HttpResponse("Hello World!")

transforms

After your view has been turned into VDOM (python dictionaries), view_to_component will call your transforms functions on every VDOM node.

This allows you to modify your view prior to rendering.

For example, if you are trying to modify the text of a node with a certain id, you can create a transform like such:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
from reactpy import component, html
from reactpy_django.components import view_to_component

from . import views


def example_transform(vdom):
    attributes = vdom.get("attributes")
    if attributes and attributes.get("id") == "hello-world":
        vdom["children"][0] = "Farewell World!"


hello_world_component = view_to_component(
    views.hello_world, transforms=[example_transform]
)


@component
def my_component():
    return html.div(
        hello_world_component(),
    )
1
2
3
4
5
from django.http import HttpResponse


def hello_world(request):
    return HttpResponse('<div id="hello-world"> Hello World! </div>')

View To Iframe

Automatically convert a Django view into an iframe element.

The contents of this iframe is handled entirely by traditional Django view rendering. While this solution is compatible with more views than view_to_component, it comes with different limitations.

Compatible with sync or async Function Based Views and Class Based Views.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from reactpy import component, html
from reactpy_django.components import view_to_iframe

from . import views

hello_world_iframe = view_to_iframe(views.hello_world)


@component
def my_component():
    return html.div(
        hello_world_iframe(),
    )
1
2
3
4
5
from django.http import HttpResponse


def hello_world(request):
    return HttpResponse("Hello World!")
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from django.apps import AppConfig
from reactpy_django.utils import register_iframe

from . import views


class ExampleAppConfig(AppConfig):
    name = "example"

    def ready(self):
        register_iframe(views.hello_world)
See Interface

Parameters

Name Type Description Default
view Callable | View | str The view function or class to convert. N/A
extra_props Mapping[str, Any] | None Additional properties to add to the iframe element. None

Returns

Type Description
constructor A function that takes *args, key, **kwargs and returns a ReactPy component. Note that *args and **kwargs are directly provided to your view.
Existing limitations

There are currently several limitations of using view_to_iframe that may be resolved in a future version.

  • No built-in method of signalling events back to the parent component.
  • All provided *args and *kwargs must be serializable values, since they are encoded into the URL.
  • The iframe will always load after the parent component.
  • CSS styling for iframe elements tends to be awkward/difficult.
How do I use this for Class Based Views?

Class Based Views are accepted by view_to_iframe as an argument.

Calling as_view() is optional, but recommended.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
from reactpy import component, html
from reactpy_django.components import view_to_iframe

from . import views

hello_world_iframe = view_to_iframe(views.HelloWorld.as_view())


@component
def my_component():
    return html.div(
        hello_world_iframe(),
    )
1
2
3
4
5
6
7
from django.http import HttpResponse
from django.views import View


class HelloWorld(View):
    def get(self, request):
        return HttpResponse("Hello World!")
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from django.apps import AppConfig
from reactpy_django.utils import register_iframe

from . import views


class ExampleAppConfig(AppConfig):
    name = "example"

    def ready(self):
        register_iframe(views.HelloWorld)
How do I provide args and kwargs to a converted view?

This component accepts *args and **kwargs arguments, which are sent to your provided view.

All provided *args and *kwargs must be serializable values, since they are encoded into the URL.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
from reactpy import component, html
from reactpy_django.components import view_to_iframe

from . import views

hello_world_iframe = view_to_iframe(
    views.hello_world,
)


@component
def my_component():
    return html.div(
        hello_world_iframe(
            "value_1",
            "value_2",
            kwarg1="abc",
            kwarg2="123",
        ),
    )
1
2
3
4
5
from django.http import HttpResponse


def hello_world(request):
    return HttpResponse("Hello World!")
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from django.apps import AppConfig
from reactpy_django.utils import register_iframe

from . import views


class ExampleAppConfig(AppConfig):
    name = "example"

    def ready(self):
        register_iframe(views.hello_world)
How do I customize this component's behavior?

This component accepts arguments that can be used to customize its behavior.

Below are all the arguments that can be used.


extra_props

This component accepts a extra_props parameter, which is a dictionary of additional properties to add to the iframe element.

For example, if you want to add a title attribute to the iframe element, you can do so like such:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
from reactpy import component, html
from reactpy_django.components import view_to_iframe

from . import views

hello_world_iframe = view_to_iframe(
    views.hello_world, extra_props={"title": "Hello World!"}
)


@component
def my_component():
    return html.div(
        hello_world_iframe(),
    )
1
2
3
4
5
from django.http import HttpResponse


def hello_world(request):
    return HttpResponse("Hello World!")
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from django.apps import AppConfig
from reactpy_django.utils import register_iframe

from . import views


class ExampleAppConfig(AppConfig):
    name = "example"

    def ready(self):
        register_iframe(views.hello_world)

Django CSS

Allows you to defer loading a CSS stylesheet until a component begins rendering. This stylesheet must be stored within Django's static files.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from reactpy import component, html
from reactpy_django.components import django_css


@component
def my_component():
    return html.div(
        django_css("css/buttons.css"),
        html.button("My Button!"),
    )
See Interface

Parameters

Name Type Description Default
static_path str The path to the static file. This path is identical to what you would use on Django's {% static %} template tag. N/A
key Key | None A key to uniquely identify this component which is unique amongst a component's immediate siblings None

Returns

Type Description
Component A ReactPy component.
Can I load static CSS using html.link instead?

While you can load stylesheets with html.link, keep in mind that loading this way does not ensure load order. Thus, your stylesheet will be loaded after your component is displayed. This would likely cause unintended visual behavior, so use this at your own discretion.

Here's an example on what you should avoid doing for Django static files:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from django.templatetags.static import static
from reactpy import component, html


@component
def my_component():
    return html.div(
        html.link({"rel": "stylesheet", "href": static("css/buttons.css")}),
        html.button("My Button!"),
    )
How do I load external CSS?

django_css can only be used with local static files.

For external CSS, you should use html.link.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from reactpy import component, html


@component
def my_component():
    return html.div(
        html.link(
            {"rel": "stylesheet", "href": "https://example.com/external-styles.css"}
        ),
        html.button("My Button!"),
    )
Why not load my CSS in <head>?

Traditionally, stylesheets are loaded in your <head> using Django's {% static %} template tag.

However, to help improve webpage load times you can use this django_css component to defer loading your stylesheet until it is needed.


Django JS

Allows you to defer loading JavaScript until a component begins rendering. This JavaScript must be stored within Django's static files.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from reactpy import component, html
from reactpy_django.components import django_js


@component
def my_component():
    return html.div(
        html.button("My Button!"),
        django_js("js/scripts.js"),
    )
See Interface

Parameters

Name Type Description Default
static_path str The path to the static file. This path is identical to what you would use on Django's {% static %} template tag. N/A
key Key | None A key to uniquely identify this component which is unique amongst a component's immediate siblings None

Returns

Type Description
Component A ReactPy component.
Can I load static JavaScript using html.script instead?

While you can load JavaScript with html.script, keep in mind that loading this way does not ensure load order. Thus, your JavaScript will likely be loaded at an arbitrary time after your component is displayed.

Here's an example on what you should avoid doing for Django static files:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from django.templatetags.static import static
from reactpy import component, html


@component
def my_component():
    return html.div(
        html.script({"src": static("js/scripts.js")}),
        html.button("My Button!"),
    )
How do I load external JS?

django_js can only be used with local static files.

For external JavaScript, you should use html.script.

1
2
3
4
5
6
7
8
9
from reactpy import component, html


@component
def my_component():
    return html.div(
        html.script({"src": "https://example.com/external-scripts.js"}),
        html.button("My Button!"),
    )
Why not load my JS in <head>?

Traditionally, JavaScript is loaded in your <head> using Django's {% static %} template tag.

However, to help improve webpage load times you can use this django_js component to defer loading your JavaScript until it is needed.


Last update: February 3, 2024
Authors: Mark Bakhit