Skip to content

Commit

Permalink
[add] AppRegistry provider methods
Browse files Browse the repository at this point in the history
Adds support for the following methods in React Native:
- setComponentProviderInstrumentationHook
- setWrapperComponentProvider
  • Loading branch information
necolas committed Apr 1, 2018
1 parent a9cacb2 commit b96dd66
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 42 deletions.
25 changes: 18 additions & 7 deletions packages/react-native-web/src/exports/AppRegistry/AppContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@
import StyleSheet from '../StyleSheet';
import View from '../View';
import { any, node } from 'prop-types';
import React, { Component } from 'react';
import React, { Component, type ComponentType } from 'react';

type Context = {
rootTag: any
};

type Props = {
WrapperComponent?: ?ComponentType<*>,
// $FlowFixMe
children?: React.Children,
rootTag: any
Expand All @@ -35,6 +36,7 @@ export default class AppContainer extends Component<Props, State> {
};

static propTypes = {
WrapperComponent: any,
children: node,
rootTag: any.isRequired
};
Expand All @@ -46,14 +48,23 @@ export default class AppContainer extends Component<Props, State> {
}

render() {
const { children, WrapperComponent } = this.props;
let innerView = (
<View
children={children}
key={this.state.mainKey}
pointerEvents="box-none"
style={styles.appContainer}
/>
);

if (WrapperComponent) {
innerView = <WrapperComponent>{innerView}</WrapperComponent>;
}

return (
<View pointerEvents="box-none" style={styles.appContainer}>
<View
children={this.props.children}
key={this.state.mainKey}
pointerEvents="box-none"
style={styles.appContainer}
/>
{innerView}
</View>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ exports[`Additional CSS for styled app 1`] = `

exports[`AppRegistry/renderApplication getApplication returns "element" and "getStyleElement" 1`] = `
<AppContainer
WrapperComponent={undefined}
rootTag={Object {}}
>
<RootComponent />
Expand Down
36 changes: 31 additions & 5 deletions packages/react-native-web/src/exports/AppRegistry/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ const emptyObject = {};
const runnables = {};

export type ComponentProvider = () => ComponentType<any>;
export type ComponentProviderInstrumentationHook = (
component: ComponentProvider
) => ComponentType<any>;
export type WrapperComponentProvider = any => ComponentType<*>;

let componentProviderInstrumentationHook: ComponentProviderInstrumentationHook = (
component: ComponentProvider
) => component();
let wrapperComponentProvider: ?WrapperComponentProvider;

export type AppConfig = {
appKey: string,
Expand All @@ -44,12 +53,21 @@ export default class AppRegistry {
return runnables[appKey].getApplication(appParameters);
}

static registerComponent(appKey: string, getComponentFunc: ComponentProvider): string {
static registerComponent(appKey: string, componentProvider: ComponentProvider): string {
runnables[appKey] = {
getApplication: ({ initialProps } = emptyObject) =>
getApplication(getComponentFunc(), initialProps),
run: ({ initialProps = emptyObject, rootTag }) =>
renderApplication(getComponentFunc(), initialProps, rootTag)
getApplication: appParameters =>
getApplication(
componentProviderInstrumentationHook(componentProvider),
appParameters.initialProps || emptyObject,
wrapperComponentProvider && wrapperComponentProvider(appParameters)
),
run: appParameters =>
renderApplication(
componentProviderInstrumentationHook(componentProvider),
appParameters.initialProps || emptyObject,
appParameters.rootTag,
wrapperComponentProvider && wrapperComponentProvider(appParameters)
)
};
return appKey;
}
Expand Down Expand Up @@ -91,6 +109,14 @@ export default class AppRegistry {
runnables[appKey].run(appParameters);
}

static setComponentProviderInstrumentationHook(hook: ComponentProviderInstrumentationHook) {
componentProviderInstrumentationHook = hook;
}

static setWrapperComponentProvider(provider: WrapperComponentProvider) {
wrapperComponentProvider = provider;
}

static unmountApplicationComponentAtRootTag(rootTag: Object) {
unmountComponentAtNode(rootTag);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,26 @@ const renderFn = process.env.NODE_ENV !== 'production' ? render : hydrate;
export default function renderApplication<Props: Object>(
RootComponent: ComponentType<Props>,
initialProps: Props,
rootTag: any
rootTag: any,
WrapperComponent?: ?ComponentType<*>
) {
invariant(rootTag, 'Expect to have a valid rootTag, instead got ', rootTag);

renderFn(
<AppContainer rootTag={rootTag}>
<AppContainer WrapperComponent={WrapperComponent} rootTag={rootTag}>
<RootComponent {...initialProps} />
</AppContainer>,
rootTag
);
}

export function getApplication(RootComponent: ComponentType<Object>, initialProps: Object): Object {
export function getApplication(
RootComponent: ComponentType<Object>,
initialProps: Object,
WrapperComponent?: ?ComponentType<*>
): Object {
const element = (
<AppContainer rootTag={{}}>
<AppContainer WrapperComponent={WrapperComponent} rootTag={{}}>
<RootComponent {...initialProps} />
</AppContainer>
);
Expand Down
62 changes: 36 additions & 26 deletions website/storybook/2-apis/AppRegistry/AppRegistryScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,22 @@ const AppRegistryScreen = () => (
AppRegistry is the control point for registering, running, prerendering, and unmounting all
apps. App root components should register themselves with{' '}
<Code>AppRegistry.registerComponent</Code>. Apps can be run by invoking{' '}
<Code>AppRegistry.runApplication</Code>
<Code>AppRegistry.runApplication</Code>.
</AppText>
</Description>

<Section title="Methods">
<DocItem
description={[
<AppText>
Register multiple applications. <Code>AppConfig</Code> type is:
</AppText>,
<Code>{`{
appKey: string;
component: ComponentProvider;
run?: function
}`}</Code>
]}
name="static registerConfig"
typeInfo="(config: Array<AppConfig>) => avoid"
description="Returns all registered app keys"
name="static getAppKeys"
typeInfo="() => Array<string>"
/>

<DocItem
description="Use this for server-side rendering to HTML. Returns a object of the given application's element, and a function to get styles once the element is rendered."
label="web"
name="static getApplication"
typeInfo="(appKey: string, appParameters: ?object) => { element: ReactElement; getStyleElement: () => ReactElement }"
/>

<DocItem
Expand All @@ -52,6 +50,21 @@ const AppRegistryScreen = () => (
typeInfo="(appKey: string, getComponentFunc: ComponentProvider) => void"
/>

<DocItem
description={[
<AppText>
Register multiple applications. <Code>AppConfig</Code> type is:
</AppText>,
<Code>{`{
appKey: string;
component: ComponentProvider;
run?: function
}`}</Code>
]}
name="static registerConfig"
typeInfo="(config: Array<AppConfig>) => avoid"
/>

<DocItem
description={
<AppText>
Expand All @@ -63,12 +76,6 @@ const AppRegistryScreen = () => (
typeInfo="(appKey: string, run: Function) => void"
/>

<DocItem
description="Returns all registered app keys"
name="static getAppKeys"
typeInfo="() => Array<string>"
/>

<DocItem
description={
<AppText>
Expand All @@ -87,6 +94,16 @@ const AppRegistryScreen = () => (
typeInfo="(appKey: string, appParameters?: object) => void"
/>

<DocItem
name="static setComponentProviderInstrumentationHook"
typeInfo="(componentProvider: func) => Component"
/>

<DocItem
name="static setWrapperComponentProvider"
typeInfo="(appParameters: object) => Component"
/>

<DocItem
description={
<AppText>
Expand All @@ -98,13 +115,6 @@ const AppRegistryScreen = () => (
name="static unmountApplicationComponentAtRootTag"
typeInfo="(rootTag: HTMLElement) => void"
/>

<DocItem
description="Use this for server-side rendering to HTML. Returns a object of the given application's element, and a function to get styles once the element is rendered."
label="web"
name="static getApplication"
typeInfo="(appKey: string, appParameters: ?object) => { element: ReactElement; getStyleElement: () => ReactElement }"
/>
</Section>
</UIExplorer>
);
Expand Down

0 comments on commit b96dd66

Please sign in to comment.