Skip to content

Commit 5a10bba

Browse files
author
User
committed
Load view_to_iframe iframes eagerly by default
`view_to_iframe` previously forced `loading="lazy"` on the rendered iframe. The browser only fetches a lazy iframe's document once it is scrolled close to the viewport. On the home page these iframes sit well below the fold, and the test harness performs no navigation (and no scroll) when it is already on "/", so a deferred lazy iframe is never fetched and a consumer waiting on the iframe's contents times out (observed intermittently on slow CI runners, e.g. `test_component_view_to_iframe_sync_func` on windows-latest). An eager iframe (the HTML default, no `loading` attribute) is a sub-resource the browser fetches as part of the parent page's initial load, so its document is guaranteed to be present as soon as the page loads. This makes loading deterministic instead of depending on the browser's load-timing heuristics, which is the real root cause of the flake. Lazy loading remains available as an opt-in for users who prefer it: pass `extra_props={"loading": "lazy"}`.
1 parent 4fd0434 commit 5a10bba

3 files changed

Lines changed: 18 additions & 1 deletion

File tree

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Don't forget to remove deprecated code on each major release!
3131

3232
### Changed
3333

34+
- `view_to_iframe` now renders its `iframe` without a `loading` attribute, so it loads **eagerly** (the HTML default) instead of lazily. The `iframe`'s document is now fetched as part of the parent page's initial load and is guaranteed to be available as soon as the page loads, rather than being deferred until it is scrolled close to the viewport. To restore the previous lazy-loading behavior, pass `extra_props={"loading": "lazy"}`.
3435
- Use one WebSocket per client webpage.
3536
- Updated dependencies: `reactpy>=2.0.0, <3.0.0` and `reactpy-router>=3.0.0, <4.0.0`.
3637
- Updated Python support to 3.11–3.14.

‎docs/src/reference/components.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,10 @@ Compatible with sync or async [Function Based Views](https://docs.djangoproject.
301301
- The `#!python iframe` will always load **after** the parent component.
302302
- CSS styling for `#!python iframe` elements tends to be awkward.
303303

304+
??? info "Loading behavior"
305+
306+
The `#!python iframe` loads **eagerly** by default: its document is fetched as part of the parent page's initial load, so it is available as soon as the page loads. If you want the browser to defer fetching the `#!python iframe`'s document until it is scrolled close to the viewport, pass `#!python extra_props={"loading": "lazy"}`.
307+
304308
??? question "How do I use this for Class Based Views?"
305309

306310
Class Based Views are accepted by `#!python view_to_iframe` as an argument.

‎src/reactpy_django/components.py‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ def constructor(
6969

7070
def view_to_iframe(view: Callable | View | str, extra_props: dict[str, Any] | None = None) -> ViewToIframeConstructor:
7171
"""
72+
Converts a Django view into a ReactPy component that is rendered within an `iframe` element.
73+
74+
The `iframe` loads eagerly by default, so its document is fetched as part of the parent page's
75+
initial load and is available as soon as the page loads. If you want the browser to defer the
76+
iframe's fetch until it is scrolled close to the viewport, pass `extra_props={"loading": "lazy"}`.
77+
7278
Args:
7379
view: The view function or class to convert, or the dotted path to the view.
7480
@@ -244,11 +250,17 @@ def _view_to_iframe(
244250
extra_props = extra_props or {}
245251
extra_props.pop("src", None)
246252

253+
# The iframe loads eagerly by default (the HTML default). An eager iframe is
254+
# a sub-resource that the browser fetches as part of the parent page's
255+
# initial load, so its document is reliably present as soon as the page
256+
# loads. The previous default of `loading="lazy"` deferred the fetch until
257+
# the iframe was scrolled close to the viewport, which made availability
258+
# non-deterministic. If you want that deferred behavior, opt in via
259+
# `extra_props={"loading": "lazy"}`.
247260
return html.iframe(
248261
{
249262
"src": reverse("reactpy:view_to_iframe", args=[dotted_path]) + query_string,
250263
"style": {"border": "none"},
251-
"loading": "lazy",
252264
}
253265
| extra_props
254266
)

0 commit comments

Comments
 (0)