From 62707aecc5e6f87cfa772b97b93f1d450862bd54 Mon Sep 17 00:00:00 2001 From: Kara Brightwell Date: Tue, 24 Jan 2023 12:08:08 +0000 Subject: [PATCH] support passing additional properties in for hydration --- components/x-increment/src/Increment.jsx | 3 ++- components/x-interaction/readme.md | 20 +++++++++++++++++++- components/x-interaction/src/Hydrate.jsx | 8 ++++++-- components/x-interaction/src/Interaction.jsx | 2 +- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/components/x-increment/src/Increment.jsx b/components/x-increment/src/Increment.jsx index d3aa1a462..e67a7f595 100644 --- a/components/x-increment/src/Increment.jsx +++ b/components/x-increment/src/Increment.jsx @@ -13,10 +13,11 @@ const withIncrementActions = withActions(({ timeout }) => ({ } })) -const BaseIncrement = ({ count, actions: { increment }, isLoading }) => ( +const BaseIncrement = ({ count, customSlot, actions: { increment }, isLoading }) => (
{count}
diff --git a/components/x-interaction/readme.md b/components/x-interaction/readme.md index b7c614c7a..0e0b9e4c3 100644 --- a/components/x-interaction/readme.md +++ b/components/x-interaction/readme.md @@ -189,7 +189,25 @@ A full example of client-side code for hydrating components: import { hydrate } from '@financial-times/x-interaction'; import '@financial-times/x-increment'; // bundle x-increment and register it with x-interaction -document.addEventListener('DOMContentLoaded', hydrate); +document.addEventListener('DOMContentLoaded', () => hydrate()); +``` + +If the underlying component requires properties that can't be serialised, such as functions or other components, you can pass these as an argument to `hydrate`, as long as they can be the same value of every instance of that component. The argument to `hydrate` is an object mapping `x-interaction`'s internal name for a component to an object containing additional properties to pass to every instaance of that component. You can access a component's internal name by calling `getComponentName`. + +For instance, `x-interaction` supports a `customSlot` property for rendering a React element into the button, but that can't be serialised. To render that on the client, we can pass it in as an additional hydration property: + +```js +import { hydrate, getComponentName } from '@financial-times/x-interaction'; +import Increment from '@financial-times/x-increment'; +import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; + +document.addEventListener('DOMContentLoaded', () => { + hydrate({ + [getComponentName(Increment)]: { + customSlot: + } + }) +}); ``` ### Triggering actions externally diff --git a/components/x-interaction/src/Hydrate.jsx b/components/x-interaction/src/Hydrate.jsx index 6367c4ab6..460653227 100644 --- a/components/x-interaction/src/Hydrate.jsx +++ b/components/x-interaction/src/Hydrate.jsx @@ -28,7 +28,7 @@ export class HydrationWrapper extends Component { } } -export function hydrate() { +export function hydrate(additionalProps = {}) { if (typeof window === 'undefined') { throw new Error('x-interaction hydrate should only be called in the browser') } @@ -51,6 +51,7 @@ export function hydrate() { } const Component = getComponentByName(component) + const additionalComponentProps = additionalProps[component] || {} if (!Component) { throw new Error( @@ -66,10 +67,13 @@ export function hydrate() { , wrapper ) diff --git a/components/x-interaction/src/Interaction.jsx b/components/x-interaction/src/Interaction.jsx index fe83deb50..3a6758025 100644 --- a/components/x-interaction/src/Interaction.jsx +++ b/components/x-interaction/src/Interaction.jsx @@ -60,4 +60,4 @@ export const withActions = (getActions, getDefaultState = {}) => (Component) => export { hydrate } from './Hydrate' export { HydrationData } from './HydrationData' export { Serialiser } from './concerns/serialiser' -export { registerComponent } from './concerns/register-component' +export { registerComponent, getComponentName } from './concerns/register-component'