Adding an optional wrapper component to app components

Summary: Changing AppContainer to render a wrapper component in it, if it exists. This wrapper is NOT a required property of AppContainer. Now, app-wide properties can be passed down via context to the container's children.

Reviewed By: sahrens, fkgozali

Differential Revision: D5283895

fbshipit-source-id: 8595e22c4b5ebf5d0e57f358152fba8a80cb2723
This commit is contained in:
Summer Kitahara 2017-06-26 16:20:39 -07:00 committed by Facebook Github Bot
parent 30352ecbf2
commit 162d92da0e
3 changed files with 47 additions and 28 deletions

View File

@ -7,6 +7,7 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule AppContainer
* @format
* @flow
*/
@ -26,6 +27,7 @@ type Context = {
type Props = {
children?: React.Children,
rootTag: number,
WrapperComponent?: ?ReactClass<*>,
};
type State = {
inspector: ?React.Element<*>,
@ -62,12 +64,13 @@ class AppContainer extends React.Component {
? null
: <Inspector
inspectedViewTag={ReactNative.findNodeHandle(this._mainRef)}
onRequestRerenderApp={(updateInspectedViewTag) => {
onRequestRerenderApp={updateInspectedViewTag => {
this.setState(
(s) => ({mainKey: s.mainKey + 1}),
() => updateInspectedViewTag(
ReactNative.findNodeHandle(this._mainRef)
)
s => ({mainKey: s.mainKey + 1}),
() =>
updateInspectedViewTag(
ReactNative.findNodeHandle(this._mainRef),
),
);
}}
/>;
@ -93,15 +96,26 @@ class AppContainer extends React.Component {
}
}
let innerView = (
<View
collapsable={!this.state.inspector}
key={this.state.mainKey}
pointerEvents="box-none"
style={styles.appContainer}
ref={ref => {
this._mainRef = ref;
}}>
{this.props.children}
</View>
);
const Wrapper = this.props.WrapperComponent;
if (Wrapper) {
innerView = <Wrapper>{innerView}</Wrapper>;
}
return (
<View style={styles.appContainer} pointerEvents="box-none">
<View
collapsable={!this.state.inspector}
key={this.state.mainKey}
pointerEvents="box-none"
style={styles.appContainer} ref={(ref) => {this._mainRef = ref;}}>
{this.props.children}
</View>
{innerView}
{yellowBox}
{this.state.inspector}
</View>

View File

@ -43,6 +43,7 @@ export type Registry = {
sections: Array<string>,
runnables: Runnables,
};
export type WrapperComponentProvider = any => ReactClass<*>;
const runnables: Runnables = {};
let runCount = 1;
@ -51,6 +52,8 @@ const tasks: Map<string, TaskProvider> = new Map();
let componentProviderInstrumentationHook: ComponentProviderInstrumentationHook =
(component: ComponentProvider) => component();
let wrapperComponentProvider: ?WrapperComponentProvider;
/**
* <div class="banner-crna-ejected">
* <h3>Project with Native Code Required</h3>
@ -78,6 +81,10 @@ let componentProviderInstrumentationHook: ComponentProviderInstrumentationHook =
* `require`d.
*/
const AppRegistry = {
setWrapperComponentProvider(provider: WrapperComponentProvider) {
wrapperComponentProvider = provider;
},
registerConfig(config: Array<AppConfig>): void {
config.forEach((appConfig) => {
if (appConfig.run) {
@ -109,7 +116,8 @@ const AppRegistry = {
renderApplication(
componentProviderInstrumentationHook(componentProvider),
appParameters.initialProps,
appParameters.rootTag
appParameters.rootTag,
wrapperComponentProvider && wrapperComponentProvider(appParameters),
)
};
if (section) {

View File

@ -7,16 +7,17 @@
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule renderApplication
* @format
* @flow
*/
'use strict';
var AppContainer = require('AppContainer');
var React = require('React');
var ReactNative = require('ReactNative');
const AppContainer = require('AppContainer');
const React = require('React');
const ReactNative = require('ReactNative');
var invariant = require('fbjs/lib/invariant');
const invariant = require('fbjs/lib/invariant');
// require BackHandler so it sets the default handler that exits the app if no listeners respond
require('BackHandler');
@ -24,20 +25,16 @@ require('BackHandler');
function renderApplication<Props: Object>(
RootComponent: ReactClass<Props>,
initialProps: Props,
rootTag: any
rootTag: any,
WrapperComponent?: ?ReactClass<*>,
) {
invariant(
rootTag,
'Expect to have a valid rootTag, instead got ', rootTag
);
invariant(rootTag, 'Expect to have a valid rootTag, instead got ', rootTag);
ReactNative.render(
<AppContainer rootTag={rootTag}>
<RootComponent
{...initialProps}
rootTag={rootTag}
/>
<AppContainer rootTag={rootTag} wrapperComponent={WrapperComponent}>
<RootComponent {...initialProps} rootTag={rootTag} />
</AppContainer>,
rootTag
rootTag,
);
}