From ab10dcc9ba38ee26ec4b339c33228df40eafadc4 Mon Sep 17 00:00:00 2001 From: Rafael Bardini Date: Mon, 6 Aug 2018 14:49:59 +0200 Subject: [PATCH] frint-react: Forward `Region` props to children components (#436) * Forward `Region` props to children components * Add missing `key` prop to mapped test components * Add tests * Update documentation --- .../src/RegionHandler.js | 23 +++++------ packages/frint-react/README.md | 4 +- packages/frint-react/src/components/Region.js | 31 ++++++--------- .../frint-react/src/components/Region.spec.js | 39 +++++++++++++------ 4 files changed, 53 insertions(+), 44 deletions(-) diff --git a/packages/frint-component-handlers/src/RegionHandler.js b/packages/frint-component-handlers/src/RegionHandler.js index 4fc1941f..1bd9bc6c 100644 --- a/packages/frint-component-handlers/src/RegionHandler.js +++ b/packages/frint-component-handlers/src/RegionHandler.js @@ -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( @@ -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) { diff --git a/packages/frint-react/README.md b/packages/frint-react/README.md index 4b2a83a0..3233d44f 100644 --- a/packages/frint-react/README.md +++ b/packages/frint-react/README.md @@ -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'; diff --git a/packages/frint-react/src/components/Region.js b/packages/frint-react/src/components/Region.js index 8abbbba5..f918733f 100644 --- a/packages/frint-react/src/components/Region.js +++ b/packages/frint-react/src/components/Region.js @@ -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 @@ -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); @@ -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 { @@ -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() { @@ -203,7 +196,7 @@ export default class Region extends React.Component { const { Component, name } = item; return ( - + ); })} diff --git a/packages/frint-react/src/components/Region.spec.js b/packages/frint-react/src/components/Region.spec.js index 927e96a4..890559bf 100644 --- a/packages/frint-react/src/components/Region.spec.js +++ b/packages/frint-react/src/components/Region.spec.js @@ -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 (
- - {(list, props) => list.map(({ Component }) => ( - + + + {(list, props) => list.map(({ Component, name }) => ( + ))}
@@ -425,8 +428,9 @@ describe('frint-react › components › Region', function () { ], }); + // apps function App1Component(props) { - return

{props.data}

; + return

App1 {props.data} {props.foo}

; } const App1 = createApp({ name: 'App1', @@ -435,22 +439,35 @@ describe('frint-react › components › Region', function () { ], }); + function App2Component(props) { + return

App2 {props.data} {props.foo}

; + } + 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 () {