react-leat
v0.3.2
Published
A library for small scale hydration of server side rendered react code.
Downloads
20
Readme
React Leat
A library for small scale hydration of server side rendered react code.
This enables a website to be completely written in React without requiring to ship the entire framework for hydration.
Installation
npm
npm install react-leat
yarn
yarn add react-leat
<Leat> Element
By utilising the <Leat>
element hydrations can be directly included in your code.
import { Leat } from 'react-leat';
const logSearchParameter = () => {
console.log(window.location.search);
}
return <div>
<Leat script={logSearchParameter}/>
</div>
Props have to be added manually since scope cannot be resolved from outside the function.
const logTest = ({ test }) => {
console.log(test);
}
const test = 1;
return <div>
<Leat
script={logSearchParameter}
props={{ test }}
/>
</div>
Props can also be React elements, these will be rendered via a hidden DOM element and are available as a regular HTMLElement
once the function runs.
const logTest = ({ getRef }) => {
document.body.appendChild(getRef('element'));
}
return <div>
<Leat
script={attachElement}
props={{
element: (
<div>Hello!</div>
)
}}
/>
</div>
A children or prop function can be supplied which offers addRef
to references the DOM as HTMLElements. These can then be retrieved using the special parameter getRef
.
const logChange = ({ getRef }) => {
// A child can be accessed directly
getRef('element').addEventListener('change', (event) => {
console.log(event.target.value);
});
// References to elements in prop elements can be accessed after they are added to the dom.
document.body.appendChild(getRef('propElement'));
getRef('button').addEventListener('click', (event) => {
console.log('clicked');
});
}
return <Leat
script={logChange}
props={{
propElement: ({ addRef }) => (
<button {...addRef('button')}>Hello!</button>
)
}}
>
{({ addRef }) => (
<input {...addRef('element')} />
)}
</Leat>;
Docs: Leat
| Props | Type | Description |
| :-------------- | :-------- | :-- |
| script
| Function
| Any function. Warning! The scope has to be contained to itself. |
| props
optional | Record<string, any>
| Any props to make available in the function itself. Has to be JSON encodable. If the prop is a function it will automatically be invoked with a Script
object. |
| children
optional | (script: Script) => ReactNode
| A function which takes a Script
and return other JSX elements. |
Docs: Script
| Props | Type | Description |
| :-------------- | :-------- | :-- |
| addRef
| (refName: string) => HydrationProps
| Adds the name to the reference pool and adds arguments which need to be added to the object. |
useClientSideScript
You can also inject scripts programmatically via the useClientSideScript
hook.
import { useClientSideScript } from 'react-leat';
const logSearchParameter = () => {
console.log(window.location.search);
}
const useClientSideScript(logSearchParameter)
return <div></div>;
or with an element
const logChange = ({ getRef }) => {
getRef('inputElem').addEventListener('change', (event) => {
console.log(event.target.value);
});
}
const { addRef } = useClientSideScript(logSearchParameter)
return <input {...addRef('inputElem')} />;
Docs: useClientScript
useClientSideScript(script: Function, props?: Record<string, any>)
| Arguments | Type | Description |
| :-------------- | :-------- | :-- |
| script
| Function
| Any function. Warning! The scope has to be contained to itself. |
| props
optional | Record<string, any>
| Any props to make available in the function itself. Has to be JSON encodable. |
ServerScriptRenderer
On the server utilise the ServerScriptRenderer
class to collect and retrieve all scripts.
Make sure to wrap your app component with .collectScripts
before calling .getScriptTag
or .getScripts
.
import ReactDOM from 'react-dom';
import React from 'react';
import { ServerScriptRenderer } from 'react-leat';
import { App } from 'client/dist/index.js'; // After some build step
const leat = new ServerScriptRenderer({ minify: true })
const renderedApp = ReactDOM.renderToString(leat.collectScripts(App));
const scriptTag = leat.getScriptTag();
const index = `<html>
<body>
${renderedApp}
${scriptTag}
</body>
</html>`;
Docs: ServerScriptRenderer
| Options | Type | Description |
| :-------------- | :-------- | :-- |
| minify
default=true | boolean
| Minify scripts using UglifyJS. |
| skipVerify
default=false | boolean
| Skip the scope verification step. |
| Member | Type | Description |
| :-------------- | :-------- | :-- |
| collectScripts
| (node: React.Node) => React.Node
| Gathers all scripts during the render step. |
| getScripts
| () => string[]
| Returns a list of IIFEs with all props encoded in it's parameter. |
| getScriptTag
| () => string
| Returns all scripts inside a <script>
tag which can immediately be injected into a HTML response. |
Other examples
To disable a script running if you (sometimes) run hydration anyway just set a window variable after hydration and check for it in your supplied scripts where applicable.
// index.js
ReactDOM.hydrateRoot(container, <App />)
window.appIsHydrated = true;
// App.js
const logChange = ({ getRef }) => {
getRef('element').addEventListener('change', (event) => {
if (window.appIsHydrated) return;
console.log(event.target.value);
});
}
return <Leat
script={logChange}
>
{({ addRef }) => (
<input {...addRef('element')} />
)}
</Leat>;