React has a very detailed documentation on this topic here.
In short:
A higher-order component is a function that takes a component and returns a new component.
In our frint-react
package, we expose an observe
function which gives us an HOC.
Install the dependencies first:
$ npm install --save rxjs react react-dom frint frint-react
Now let's say, we have a basic React component:
// components/Root.js
import React from 'react';
function MyComponent(props) {
return (
<p>Name: {props.name}</p>
);
}
export default MyComponent;
The component just renders a name, which is given to it as props.
And the App definition happens to looks like this:
// app/index.js
import { createApp } from 'frint';
import Root from '../components/Root';
export default createApp({
name: 'MyAppNameHere',
providers: [
{
name: 'component',
useValue: Root
}
]
})
But we want to inject the App's name to the component, and we could easily do that using observe
:
// components/Root.js
import { observe } from 'frint-react';
function MyComponent(props) {
return (
<p>Name: {props.name}</p>
);
}
export default observe(function (app) {
// `app` is our App's instance
// return a props-compatible object from here
return {
name: app.getName() // `MyAppNameHere`
};
})(MyComponent);
Now your stateless component will receive a prop appName
with the value MyAppNameHere
.
You can also stream props (that change over time) expressed with an RxJS Observable. Imagine, you want to pass an interval
prop that updates every second. This can be done as follows:
import React from 'react';
import { observe } from 'frint-react';
import { interval } from 'rxjs/observable/interval';
import { map } from 'rxjs/operators/map';
function MyComponent(props) {
// `props.interval` is an integer that's incrementing every second
}
export default observe(function (app) {
// will keep emitting an object with this structure:
// `{ interval: x }` where `x` is an integer
const interval$ = interval(1000).pipe(
map(x => ({ interval: x }))
);
return interval$;
})(MyComponent);
Now MyComponent
will keep re-rendering as it keeps receiving new props object where the interval
key increments every second.
Now when your App gets rendered, your Root component would show your App's name:
// index.js
import { render } from 'frint-react';
import App from './app';
const app = new App();
render(app, document.getElementById('root'));