Expand description
React islands for Autumn apps: React 19 components inside Maud + htmx pages.
-
Build your components with a bundler. The entry file registers them (the README has a version that also checks the global):
import { createElement, version } from "react"; import { flushSync } from "react-dom"; import { createRoot } from "react-dom/client"; import { Counter } from "./Counter.jsx"; (window.autumnReact ??= []).push({ createElement, createRoot, flushSync, version, components: { Counter }, }); -
Embed the build output as a
PluginAssetsbundle and install it:
use autumn_plugin_react::{Island, ReactPlugin, react_bundle, react_script};
use autumn_web::assets::PluginAssets;
use autumn_web::prelude::*;
static ISLANDS: PluginAssets = PluginAssets::from_files(
"app-islands",
&[("islands.js", b"/* esbuild output */")],
);
#[get("/")]
async fn index() -> AutumnResult<Markup> {
let counter = Island::new("Counter")
.props(&serde_json::json!({ "start": 3 }))?
.fallback(html! { p { "Count: 3" } });
Ok(html! {
html {
head { (react_script()) (react_bundle(&ISLANDS)) }
body { (counter) }
}
})
}
autumn_web::app()
.plugin(ReactPlugin::new().bundle(&ISLANDS))
.routes(routes![index])
.run()
.await;The loader (react-islands.js) mounts each island with createRoot. It
mounts islands that htmx swaps in and unmounts islands that htmx swaps
out. A data-react-props change renders the same root again, so React
keeps the state. It uses no inline script and no eval, so it works
under the default CSP (script-src 'self').
§Security
The loader mounts each data-react-island element in the page. If your
app shows user HTML, the sanitizer must remove data-react-*, hx-*
and data-hx-* attributes. data-react-ignore alone is not sufficient:
an htmx out-of-band swap can move an element out of it. Do not spread
untrusted props onto DOM elements.
Structs§
- Island
- One React island: an element that the loader mounts a component into.
- Props
Update - New props for mounted islands, sent in an
HX-Triggerheader. - React
Plugin - Installs React islands in an Autumn app.
Enums§
- Attr
Error - The error from
Island::attr. - Json
Kind - The kind of a JSON value that is not an object.
- Mount
When - When the loader mounts an island.
- Props
Error - The error from
Island::props.
Constants§
- ASSETS_
NAMESPACE - URL namespace of the loader bundle:
/static/_plugins/react/. - LOADER_
JS - Logical path of the loader in
REACT_ASSETS. - PLUGIN_
NAME - The crate name.
ReactPluginwith no app bundles uses it as its plugin name. EachReactPlugindeclares it in its contract. - PROPS_
EVENT - The DOM event that the loader reads new props from.
Statics§
- REACT_
ASSETS - The loader bundle. It holds one file,
LOADER_JS.
Functions§
- react_
bundle - Renders the tags of an app bundle, in this order:
- react_
script - Renders the
<script defer>tag of the island loader.