11# @fictjs/react
22
3+ [ ![ Node CI] ( https://github.com/fictjs/react/actions/workflows/nodejs.yml/badge.svg )] ( https://github.com/fictjs/react/actions/workflows/nodejs.yml )
4+ [ ![ npm] ( https://img.shields.io/npm/v/@fictjs/react.svg )] ( https://www.npmjs.com/package/@fictjs/react )
5+ ![ license] ( https://img.shields.io/npm/l/@fictjs/react )
6+
37React interoperability layer for [ Fict] ( https://github.com/nicepkg/fict ) — embed React components inside Fict applications as controlled islands with SSR, lazy loading, and fine-grained prop reactivity.
48
59## Why
@@ -8,14 +12,14 @@ Fict uses its own compiler-driven reactivity model. When you need to reuse an ex
812
913## Features
1014
11- | Capability | API | When to use |
12- | ---| ---| ---|
13- | Eager wrapping | ` reactify ` | The React component is already imported |
14- | Declarative island | ` ReactIsland ` | Inline island with a ` props ` getter |
15- | Resumable / lazy | ` reactify$ ` | The component should be lazy-loaded via QRL |
16- | Static loader | ` installReactIslands ` | Mount islands from plain HTML attributes (no Fict runtime) |
17- | Serializable callbacks | ` reactAction$ ` | Pass Fict actions across the serialization boundary |
18- | Vite preset | ` fictReactPreset ` | Isolate React JSX transform from Fict's compiler |
15+ | Capability | API | When to use |
16+ | ---------------------- | --------------------- | ---------------------------------------------------------- |
17+ | Eager wrapping | ` reactify ` | The React component is already imported |
18+ | Declarative island | ` ReactIsland ` | Inline island with a ` props ` getter |
19+ | Resumable / lazy | ` reactify$ ` | The component should be lazy-loaded via QRL |
20+ | Static loader | ` installReactIslands ` | Mount islands from plain HTML attributes (no Fict runtime) |
21+ | Serializable callbacks | ` reactAction$ ` | Pass Fict actions across the serialization boundary |
22+ | Vite preset | ` fictReactPreset ` | Isolate React JSX transform from Fict's compiler |
1923
2024## Install
2125
@@ -48,10 +52,7 @@ import { fictReactPreset } from '@fictjs/react/preset'
4852import fict from ' @fictjs/vite-plugin'
4953
5054export default defineConfig ({
51- plugins: [
52- fict (),
53- ... fictReactPreset (),
54- ],
55+ plugins: [fict (), ... fictReactPreset ()],
5556})
5657```
5758
@@ -142,8 +143,8 @@ For advanced Fict-serialized values (for example action refs), prefer server out
142143import { installReactIslands } from ' @fictjs/react/loader'
143144
144145const cleanup = installReactIslands ({
145- observe: true , // Watch for dynamically added islands
146- defaultClient: ' idle' , // Fallback client strategy
146+ observe: true , // Watch for dynamically added islands
147+ defaultClient: ' idle' , // Fallback client strategy
147148 visibleRootMargin: ' 200px' ,
148149})
149150
@@ -187,12 +188,12 @@ const RemoteEditor = reactify$({
187188
188189Control when each island mounts on the client:
189190
190- | Strategy | Behavior |
191- | ---| ---|
192- | ` 'load' ` | Mount immediately (via microtask). ** Default.** |
193- | ` 'idle' ` | Mount during idle time (` requestIdleCallback ` , falls back to ` setTimeout(…, 1) ` ) |
191+ | Strategy | Behavior |
192+ | ----------- | ------------------------------------------------------------------------------------------------------------------------ |
193+ | ` 'load' ` | Mount immediately (via microtask). ** Default.** |
194+ | ` 'idle' ` | Mount during idle time (` requestIdleCallback ` , falls back to ` setTimeout(…, 1) ` ) |
194195| ` 'visible' ` | Mount when the host element enters the viewport (` IntersectionObserver ` with configurable ` rootMargin ` , default ` 200px ` ) |
195- | ` 'only' ` | Client-only rendering — no SSR, no hydration |
196+ | ` 'only' ` | Client-only rendering — no SSR, no hydration |
196197
197198When ` ssr ` is ` true ` (the default), the React subtree is rendered to HTML on the server. On the client, the island hydrates (` hydrateRoot ` ) if SSR content is present, otherwise it creates a fresh root (` createRoot ` ).
198199
@@ -204,13 +205,13 @@ Wraps a React component as a Fict component. Props flow reactively from the Fict
204205
205206** Options** (` ReactInteropOptions ` ):
206207
207- | Option | Type | Default | Description |
208- | ---| ---| ---| ---|
209- | ` ssr ` | ` boolean ` | ` true ` | Server-side render the React subtree |
210- | ` client ` | ` ClientDirective ` | ` 'load' ` | Client mount strategy |
211- | ` visibleRootMargin ` | ` string ` | ` '200px' ` | Margin for ` 'visible' ` strategy |
212- | ` identifierPrefix ` | ` string ` | ` '' ` | React ` useId ` prefix for multi-root pages |
213- | ` actionProps ` | ` string[] ` | ` [] ` | Additional callback prop names to materialize |
208+ | Option | Type | Default | Description |
209+ | ------------------- | ----------------- | --------- | --------------------------------------------- |
210+ | ` ssr ` | ` boolean ` | ` true ` | Server-side render the React subtree |
211+ | ` client ` | ` ClientDirective ` | ` 'load' ` | Client mount strategy |
212+ | ` visibleRootMargin ` | ` string ` | ` '200px' ` | Margin for ` 'visible' ` strategy |
213+ | ` identifierPrefix ` | ` string ` | ` '' ` | React ` useId ` prefix for multi-root pages |
214+ | ` actionProps ` | ` string[] ` | ` [] ` | Additional callback prop names to materialize |
214215
215216### ` ReactIsland<P>(props) `
216217
@@ -222,25 +223,25 @@ Creates a lazy-loadable Fict component backed by a QRL.
222223
223224** Additional options** (` ReactifyQrlOptions<P> ` ):
224225
225- | Option | Type | Description |
226- | ---| ---| ---|
227- | ` module ` | ` string ` | Module URL, usually ` import.meta.url ` |
228- | ` export ` | ` string ` | Export name (default: ` 'default' ` ) |
229- | ` component ` | ` ComponentType<P> ` | Optional eager reference for SSR |
226+ | Option | Type | Description |
227+ | ----------- | ------------------ | ------------------------------------- |
228+ | ` module ` | ` string ` | Module URL, usually ` import.meta.url ` |
229+ | ` export ` | ` string ` | Export name (default: ` 'default' ` ) |
230+ | ` component ` | ` ComponentType<P> ` | Optional eager reference for SSR |
230231
231232### ` installReactIslands(options?) `
232233
233234Scans the document for ` [data-fict-react] ` hosts and mounts them. Returns a cleanup function.
234235
235236** Options** (` ReactIslandsLoaderOptions ` ):
236237
237- | Option | Type | Default | Description |
238- | ---| ---| ---| ---|
239- | ` document ` | ` Document ` | ` document ` | Document to scan |
240- | ` selector ` | ` string ` | ` '[data-fict-react]' ` | CSS selector for island hosts |
241- | ` observe ` | ` boolean ` | ` true ` | Watch for dynamic additions/removals |
242- | ` defaultClient ` | ` ClientDirective ` | ` 'load' ` | Fallback client strategy |
243- | ` visibleRootMargin ` | ` string ` | ` '200px' ` | Margin for ` 'visible' ` strategy |
238+ | Option | Type | Default | Description |
239+ | ------------------- | ----------------- | --------------------- | ------------------------------------ |
240+ | ` document ` | ` Document ` | ` document ` | Document to scan |
241+ | ` selector ` | ` string ` | ` '[data-fict-react]' ` | CSS selector for island hosts |
242+ | ` observe ` | ` boolean ` | ` true ` | Watch for dynamic additions/removals |
243+ | ` defaultClient ` | ` ClientDirective ` | ` 'load' ` | Fallback client strategy |
244+ | ` visibleRootMargin ` | ` string ` | ` '200px' ` | Margin for ` 'visible' ` strategy |
244245
245246### ` reactAction$(moduleId, exportName?) `
246247
@@ -254,26 +255,26 @@ Creates an action ref from a raw QRL string.
254255
255256Returns Vite plugins that scope the React JSX transform to a directory.
256257
257- | Option | Type | Default | Description |
258- | ---| ---| ---| ---|
259- | ` include ` | ` FilterPattern ` | ` [/src\/react\/.*\.[jt]sx?$/] ` | Files to transform with React JSX |
260- | ` exclude ` | ` FilterPattern ` | — | Files to exclude |
261- | ` react ` | ` ReactPluginOptions ` | — | Additional ` @vitejs/plugin-react ` options |
258+ | Option | Type | Default | Description |
259+ | --------- | -------------------- | ------------------------------ | ----------------------------------------- |
260+ | ` include ` | ` FilterPattern ` | ` [/src\/react\/.*\.[jt]sx?$/] ` | Files to transform with React JSX |
261+ | ` exclude ` | ` FilterPattern ` | — | Files to exclude |
262+ | ` react ` | ` ReactPluginOptions ` | — | Additional ` @vitejs/plugin-react ` options |
262263
263264## Host Attributes
264265
265266When using the loader or resumable mode, the following data attributes control island behavior:
266267
267- | Attribute | Mutable | Purpose |
268- | ---| ---| ---|
269- | ` data-fict-react ` | ` * ` | QRL pointing to the React component module |
270- | ` data-fict-react-props ` | yes | URL-encoded serialized props |
271- | ` data-fict-react-action-props ` | yes | URL-encoded JSON array of custom action prop names |
272- | ` data-fict-react-client ` | no | Client strategy (` load ` / ` idle ` / ` visible ` / ` only ` ) |
273- | ` data-fict-react-ssr ` | no | ` '1' ` if SSR content is present |
274- | ` data-fict-react-prefix ` | no | React ` useId ` identifier prefix |
275- | ` data-fict-react-host ` | — | Marks element as a React island host |
276- | ` data-fict-react-mounted ` | — | Set to ` '1' ` after the island mounts |
268+ | Attribute | Mutable | Purpose |
269+ | ------------------------------ | ------- | ------------------------------------------------------ |
270+ | ` data-fict-react ` | ` * ` | QRL pointing to the React component module |
271+ | ` data-fict-react-props ` | yes | URL-encoded serialized props |
272+ | ` data-fict-react-action-props ` | yes | URL-encoded JSON array of custom action prop names |
273+ | ` data-fict-react-client ` | no | Client strategy (` load ` / ` idle ` / ` visible ` / ` only ` ) |
274+ | ` data-fict-react-ssr ` | no | ` '1' ` if SSR content is present |
275+ | ` data-fict-react-prefix ` | no | React ` useId ` identifier prefix |
276+ | ` data-fict-react-host ` | — | Marks element as a React island host |
277+ | ` data-fict-react-mounted ` | — | Set to ` '1' ` after the island mounts |
277278
278279` * ` Changing the QRL disposes the current root and creates a new one.
279280
0 commit comments