Skip to content

Commit

Permalink
frint-react: Forward Region props to children components (#436)
Browse files Browse the repository at this point in the history
* Forward `Region` props to children components

* Add missing `key` prop to mapped test components

* Add tests

* Update documentation
  • Loading branch information
rbardini authored Aug 6, 2018
1 parent 23b239f commit ab10dcc
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 44 deletions.
23 changes: 10 additions & 13 deletions packages/frint-component-handlers/src/RegionHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,12 @@ export default {

const appInstance = rootApp.getAppInstance(appName, ...regionArgs);
if (appInstance) {
this.sendProps(appInstance, {
name: this.getProp('name'),
uniqueKey: this.getProp('uniqueKey'),
data: this.getProp('data'),
});
const {
children,
className,
...props
} = this.getProps();
this.sendProps(appInstance, props);
}

this.setData(
Expand Down Expand Up @@ -110,18 +111,14 @@ export default {
},
afterUpdate(newProps = null) {
const {
name = this.getProp('name'),
uniqueKey = this.getProp('uniqueKey'),
data = this.getProp('data'),
children,
className,
...props
} = newProps || {};

this.getData('listForRendering')
.filter(item => item.instance)
.forEach(item => this.sendProps(item.instance, {
name,
uniqueKey,
data,
}));
.forEach(item => this.sendProps(item.instance, props));
},
beforeDestroy() {
if (this._subscription) {
Expand Down
4 changes: 3 additions & 1 deletion packages/frint-react/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,9 @@ We have just made our simple Component reactive, by wrapping it with `observe`.

### Observing Region's data

In previous example, we showed you how to access Region's data via `RegionService`. Now let's see how we can pass it to your App's component too:
In previous example, we showed you how to access Region's data via `RegionService`. Now let's see how we can pass it to your App's component too.

All Region props but `children` and `className` are forwarded to the App's component by default. However, if you prefer a reactive approach:

```js
import { map } from 'rxjs/operators/map';
Expand Down
31 changes: 12 additions & 19 deletions packages/frint-react/src/components/Region.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ export default class Region extends React.Component {

getListForRendering(list, rootApp, listForRendering = []) {
const {
uniqueKey,
data
children,
className,
...props
} = this.props;

return list
Expand All @@ -72,12 +73,12 @@ export default class Region extends React.Component {
return null;
}

const regionArgs = uniqueKey
? [this.props.name, uniqueKey]
const regionArgs = this.props.uniqueKey
? [this.props.name, this.props.uniqueKey]
: [this.props.name];

if (
uniqueKey &&
this.props.uniqueKey &&
!rootApp.hasAppInstance(name, ...regionArgs)
) {
rootApp.instantiateApp(name, ...regionArgs);
Expand All @@ -86,11 +87,7 @@ export default class Region extends React.Component {
const instance = rootApp.getAppInstance(name, ...regionArgs);

if (instance) {
Region.sendProps(instance, {
name: this.props.name,
uniqueKey,
data,
});
Region.sendProps(instance, props);
}

return {
Expand Down Expand Up @@ -148,18 +145,14 @@ export default class Region extends React.Component {

componentWillReceiveProps(nextProps) {
const {
name = this.props.name,
uniqueKey = this.props.uniqueKey,
data = this.props.data,
children,
className,
...props
} = nextProps;

this.state.listForRendering
.filter(item => item.instance)
.forEach(item => Region.sendProps(item.instance, {
name,
uniqueKey,
data,
}));
.forEach(item => Region.sendProps(item.instance, props));
}

componentWillUnmount() {
Expand Down Expand Up @@ -203,7 +196,7 @@ export default class Region extends React.Component {
const { Component, name } = item;

return (
<Component key={`app-${name}`} />
<Component {...props} key={`app-${name}`} />
);
})}
</div>
Expand Down
39 changes: 28 additions & 11 deletions packages/frint-react/src/components/Region.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -405,13 +405,16 @@ describe('frint-react › components › Region', function () {

it('should pass props to render the component', function () {
const data = 'data';
const foo = 'foo';

// root
function RootComponent() {
return (
<div>
<Region data={data} name="sidebar">
{(list, props) => list.map(({ Component }) => (
<Component data={props.data} />
<Region data={data} foo={foo} name="sidebar1" />
<Region data={data} foo={foo} name="sidebar2">
{(list, props) => list.map(({ Component, name }) => (
<Component data={props.data} foo={props.foo} key={`app-${name}`} />
))}
</Region>
</div>
Expand All @@ -425,8 +428,9 @@ describe('frint-react › components › Region', function () {
],
});

// apps
function App1Component(props) {
return <p>{props.data}</p>;
return <p>App1 {props.data} {props.foo}</p>;
}
const App1 = createApp({
name: 'App1',
Expand All @@ -435,22 +439,35 @@ describe('frint-react › components › Region', function () {
],
});

function App2Component(props) {
return <p>App2 {props.data} {props.foo}</p>;
}
const App2 = createApp({
name: 'App2',
providers: [
{ name: 'component', useValue: App2Component },
],
});

// render
window.app = new RootApp();
const rootApp = new RootApp();
render(
window.app,
rootApp,
document.getElementById('root')
);

// register apps
window.app.registerApp(App1, {
regions: ['sidebar'],
weight: 10,
rootApp.registerApp(App1, {
regions: ['sidebar1'],
});
rootApp.registerApp(App2, {
regions: ['sidebar2'],
});

// verify
const paragraph = document.querySelector('p');
expect(paragraph.innerHTML).to.equal(data);
const paragraphs = document.querySelectorAll('p');
expect(paragraphs[0].innerHTML).to.equal(`App1 ${data} ${foo}`);
expect(paragraphs[1].innerHTML).to.equal(`App2 ${data} ${foo}`);
});

it('should render when renderToString is called', function () {
Expand Down

0 comments on commit ab10dcc

Please sign in to comment.