@wrdagency/react-islands
Version:
Created by Kyle Cooper at [WRD.agency](https://webresultsdirect.com)
111 lines (73 loc) • 4.6 kB
Markdown
# React Islands
Created by Kyle Cooper at [WRD.agency](https://webresultsdirect.com)
React Islands is a way of introducing pockets of React into otherwise static pages, with an option for build-type rendering to help with layout shift. We developed React Islands as a way of introducing React-based interactivity sprinkled into places on WordPress sites (rendered via PHP).
## Example Setup
Create your island. Here we use an existing component and use our Islands directory to only setup the islands and not for worrying about functionality.
```
// ./islands/my-component.tsx
import MyComponent from "./components";
import { createIsland } from "@wrdagency/react-islands";
export const myComponentIsland = createIsland(MyComponent, {
name: "my-component",
});
```
```
// ./islands/index.ts
export * from "./my-component";
```
On the client you can then render each of those islands. They'll automatically hook into the DOM where the selector is matched (similar to a portal) to create an island of reactivity.
```
// index.ts
import * as islands from "./islands";
import { hydrateIslands } from "@wrdagency/react-islands";
hydrateIslands( islands );
```
Create a pre-render script. You can configure your build tool to use this as a seperate entrypoint.
```
// prerender.ts
import path from "node:path";
import { fileURLToPath } from "node:url";
import * as islands from "./islands";
import { prerenderIslands } from "@wrdagency/react-islands/server";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const outDir = path.resolve(__dirname, "ssg");
prerenderIslands({ islands, outDir });
```
For our example we're using Vite. We'll build our prerendering script.
```
npx vite build --ssr ./src/prerender.tsx --outDir ./dist
```
And then we can run that compiled script. It'll create all of our statically rendered islands and put them into the `outDir` we specified.
```
node ./dist/prerender.js
```
For convenience we'd recommend setting up a script in your `package.json` for this like so:
```
"scripts": {
"prerender": "npx vite build --ssr ./src/prerender.tsx --outDir ./dist && node ./dist/prerender.js",
},
```
## API
### `createIsland`
`(component: React.FC, options: IslandOpts) => Island`
Creates an island.
#### `IslandOpts`
| Options | Type | Default | Description |
| ------------ | -------- | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| name | string | Required | The name of the island. Used for the default selector and the filename of pre-rendering. |
| selector | string? | [data-hydrate="{{NAME}}"] | The query selector to match for the islands root. |
| multiple | boolean? | false | If enabled, the island will by instantiated for every element that matches the selector, not just the first. |
| keepChildren | boolean? | false | If enabled, the children props of the island component will be set to the raw HTML of the existing node's children. Experimental. |
### `withProps`
`<T>(component: React.FC<T>, props: Partial<T>) => React.FC<T>`
Creates a version of your React component with props already set. Useful for creating multiple islands with variants of the same component.
### `isServer`
`() => boolean`
Checks if the current environment is the server. Useful for disabled certain features not available during the prerender step.
### `prerenderIslands`
`(options: PrerenderIslandsOpts) => Promise<void>`
| Option | Type | Description |
| ------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| islands | Record<string, Island> | The islands the pre-render. The key of the record is not used, it's just useful to accept a record if we're using `import * as Islands`. |
| ourDir | string | Path of the directory to output the static HTML to. This directory will be emptied before pre-rendering begins. |