[add] AppRegistry provider methods

Adds support for the following methods in React Native:
- setComponentProviderInstrumentationHook
- setWrapperComponentProvider
This commit is contained in:
Nicolas Gallagher
2018-04-01 10:26:17 -07:00
parent a9cacb2ef5
commit b96dd668d3
5 changed files with 96 additions and 43 deletions
@@ -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
@@ -35,6 +36,7 @@ export default class AppContainer extends Component<Props, State> {
};
static propTypes = {
WrapperComponent: any,
children: node,
rootTag: any.isRequired
};
@@ -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>
);
}
@@ -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 />
+31 -5
View File
@@ -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,
@@ -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;
}
@@ -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);
}
@@ -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>
);
@@ -19,11 +19,37 @@ 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="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
description={
<AppText>
Register a component provider under the given <Code>appKey</Code>.
</AppText>
}
example={{
code: 'AppRegistry.registerComponent("MyApp", () => AppComponent)'
}}
name="static registerComponent"
typeInfo="(appKey: string, getComponentFunc: ComponentProvider) => void"
/>
<DocItem
description={[
<AppText>
@@ -39,19 +65,6 @@ const AppRegistryScreen = () => (
typeInfo="(config: Array<AppConfig>) => avoid"
/>
<DocItem
description={
<AppText>
Register a component provider under the given <Code>appKey</Code>.
</AppText>
}
example={{
code: 'AppRegistry.registerComponent("MyApp", () => AppComponent)'
}}
name="static registerComponent"
typeInfo="(appKey: string, getComponentFunc: ComponentProvider) => void"
/>
<DocItem
description={
<AppText>
@@ -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>
@@ -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>
@@ -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>
);