Skip to content

Error handlingยค

The built-in ErrorFallback component catches errors during component rendering and displays fallback content instead. This is similar to React's ErrorBoundary component.

In this scenario, we have a WeatherWidget component that simulates fetching data from a weather API, which we wrap in the built-in ErrorFallback component.

We have two cases:

  1. API call succeeds. The WeatherWidget component renders the weather information as expected.
  2. API call fails. The ErrorFallback component catches the error and display a user-friendly message instead of breaking the page.
{% component "error_fallback" %}
    {% fill "content" %}
        {% component "weather_widget" location="Atlantis" / %}
    {% endfill %}
    {% fill "fallback" %}
        <p style="color: red;">
            Could not load weather data for <strong>Atlantis</strong>.
            The location may not be supported or the service is temporarily down.
        </p>
    {% endfill %}
{% endcomponent %}

ErrorFallback example

Definitionยค

# ruff: noqa: S311
import random
from typing import NamedTuple

from django_components import Component, register, types

DESCRIPTION = "A component that catches errors and displays fallback content, similar to React's ErrorBoundary."


@register("weather_widget")
class WeatherWidget(Component):
    class Kwargs(NamedTuple):
        location: str
        simulate_error: bool = False

    def get_template_data(self, args, kwargs: Kwargs, slots, context):
        if kwargs.simulate_error:
            raise OSError(f"Failed to connect to weather service for '{kwargs.location}'.")

        return {
            "location": kwargs.location,
            "temperature": f"{random.randint(10, 30)}ยฐC",
            "condition": random.choice(["Sunny", "Cloudy", "Rainy"]),
        }

    template: types.django_html = """
        <div class="bg-white rounded-lg shadow-md p-6">
            <h3 class="text-xl font-semibold text-gray-800 mb-2">
                Weather in {{ location }}
            </h3>
            <p class="text-gray-600">
                <strong class="font-medium text-gray-700">Temperature:</strong>
                {{ temperature }}
            </p>
            <p class="text-gray-600">
                <strong class="font-medium text-gray-700">Condition:</strong>
                {{ condition }}
            </p>
        </div>
    """

Exampleยค

To see the component in action, you can set up a view and URL pattern as shown below.

views.pyยค

from django.http import HttpRequest, HttpResponse
from django.utils.safestring import mark_safe

from django_components import Component, types


class ErrorFallbackPage(Component):
    class Media:
        js = (
            mark_safe(
                '<script src="https://cdn.tailwindcss.com?plugins=forms,typography,aspect-ratio,line-clamp,container-queries"></script>'
            ),
        )

    template: types.django_html = """
        {% load component_tags %}
        <html>
            <head>
                <title>ErrorFallback Example</title>
            </head>
            <body class="bg-gray-100 p-8">
                <div class="max-w-2xl mx-auto bg-white p-6 rounded-lg shadow-md">
                    <h1 class="text-2xl font-bold mb-4">Weather API Widget Example</h1>
                    <p class="text-gray-600 mb-6">
                        This example demonstrates using ErrorFallback to handle potential API failures gracefully.
                    </p>

                    <div class="mb-8">
                        <h2 class="text-xl font-semibold mb-2">Case 1: API call is successful</h2>
                        {% component "error_fallback" %}
                            {% fill "content" %}
                                {% component "weather_widget" location="New York" / %}
                            {% endfill %}
                            {% fill "fallback" %}
                                <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
                                    <strong class="font-bold">Error:</strong>
                                    <span class="block sm:inline">Could not load weather data.</span>
                                </div>
                            {% endfill %}
                        {% endcomponent %}
                    </div>

                    <div>
                        <h2 class="text-xl font-semibold mb-2">Case 2: API call fails</h2>
                        {% component "error_fallback" %}
                            {% fill "content" %}
                                {% component "weather_widget" location="Atlantis" simulate_error=True / %}
                            {% endfill %}
                            {% fill "fallback" %}
                                <div class="bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative" role="alert">
                                    <strong class="font-bold">Error:</strong>
                                    <span class="block sm:inline">
                                        Could not load weather data for
                                        <strong>Atlantis</strong>.
                                        The location may not be supported or the service is temporarily down.
                                    </span>
                                </div>
                            {% endfill %}
                        {% endcomponent %}
                    </div>
                </div>
            </body>
        </html>
    """  # noqa: E501

    class View:
        def get(self, request: HttpRequest) -> HttpResponse:
            return ErrorFallbackPage.render_to_response(request=request)

urls.pyยค

from django.urls import path

from examples.pages.error_fallback import ErrorFallbackPage

urlpatterns = [
    path("examples/error_fallback", ErrorFallbackPage.as_view(), name="error_fallback"),
]