Skip to content

Commit f360dce

Browse files
Merge pull request #691 from Financial-Times/hydration-props
2 parents 7ce5df3 + 62707ae commit f360dce

File tree

4 files changed

+28
-5
lines changed

4 files changed

+28
-5
lines changed

components/x-increment/src/Increment.jsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ const withIncrementActions = withActions(({ timeout }) => ({
1313
}
1414
}))
1515

16-
const BaseIncrement = ({ count, actions: { increment }, isLoading }) => (
16+
const BaseIncrement = ({ count, customSlot, actions: { increment }, isLoading }) => (
1717
<div>
1818
<span>{count}</span>
1919
<button onClick={() => increment()} disabled={isLoading}>
20+
{customSlot}
2021
{isLoading ? 'Loading...' : 'Increment'}
2122
</button>
2223
</div>

components/x-interaction/readme.md

+19-1
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,25 @@ A full example of client-side code for hydrating components:
189189
import { hydrate } from '@financial-times/x-interaction';
190190
import '@financial-times/x-increment'; // bundle x-increment and register it with x-interaction
191191

192-
document.addEventListener('DOMContentLoaded', hydrate);
192+
document.addEventListener('DOMContentLoaded', () => hydrate());
193+
```
194+
195+
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`.
196+
197+
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:
198+
199+
```js
200+
import { hydrate, getComponentName } from '@financial-times/x-interaction';
201+
import Increment from '@financial-times/x-increment';
202+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
203+
204+
document.addEventListener('DOMContentLoaded', () => {
205+
hydrate({
206+
[getComponentName(Increment)]: {
207+
customSlot: <FontAwesomeIcon icon='plus' />
208+
}
209+
})
210+
});
193211
```
194212

195213
### Triggering actions externally

components/x-interaction/src/Hydrate.jsx

+6-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export class HydrationWrapper extends Component {
2828
}
2929
}
3030

31-
export function hydrate() {
31+
export function hydrate(additionalProps = {}) {
3232
if (typeof window === 'undefined') {
3333
throw new Error('x-interaction hydrate should only be called in the browser')
3434
}
@@ -51,6 +51,7 @@ export function hydrate() {
5151
}
5252

5353
const Component = getComponentByName(component)
54+
const additionalComponentProps = additionalProps[component] || {}
5455

5556
if (!Component) {
5657
throw new Error(
@@ -66,10 +67,13 @@ export function hydrate() {
6667
<HydrationWrapper
6768
{...{
6869
Component,
69-
props,
7070
id,
7171
wrapper
7272
}}
73+
props={{
74+
...props,
75+
...additionalComponentProps
76+
}}
7377
/>,
7478
wrapper
7579
)

components/x-interaction/src/Interaction.jsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,4 @@ export const withActions = (getActions, getDefaultState = {}) => (Component) =>
6060
export { hydrate } from './Hydrate'
6161
export { HydrationData } from './HydrationData'
6262
export { Serialiser } from './concerns/serialiser'
63-
export { registerComponent } from './concerns/register-component'
63+
export { registerComponent, getComponentName } from './concerns/register-component'

0 commit comments

Comments
 (0)