[add] AppRegistry support for React render callback

Close #858

Co-authored-by: Nicolas Gallagher <nicolasgallagher@gmail.com>
This commit is contained in:
slorber
2018-03-07 19:53:53 +01:00
committed by Nicolas Gallagher
parent 4c59343fd3
commit 7a3a9a5c3f
5 changed files with 37 additions and 13 deletions

View File

@@ -9,7 +9,7 @@ exports[`Additional CSS for styled app 1`] = `
.rn-borderLeftWidth-150mub4{border-left-width:1234px}"
`;
exports[`AppRegistry/renderApplication getApplication returns "element" and "getStyleElement" 1`] = `
exports[`AppRegistry getApplication returns "element" and "getStyleElement" 1`] = `
<AppContainer
WrapperComponent={undefined}
rootTag={Object {}}
@@ -18,7 +18,7 @@ exports[`AppRegistry/renderApplication getApplication returns "element" and "get
</AppContainer>
`;
exports[`AppRegistry/renderApplication getApplication returns "element" and "getStyleElement" 2`] = `
exports[`AppRegistry getApplication returns "element" and "getStyleElement" 2`] = `
"<style id=\\"react-native-stylesheet\\">@media all{
html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);}
body{margin:0;}

View File

@@ -1,7 +1,7 @@
/* eslint-env jasmine, jest */
import AppRegistry from '..';
import ExecutionEnvironment from 'fbjs/lib/ExecutionEnvironment';
import { getApplication } from '../renderApplication';
import React from 'react';
import ReactDOMServer from 'react-dom/server';
import { render } from 'enzyme';
@@ -10,7 +10,7 @@ import View from '../../View';
const RootComponent = () => <div />;
describe('AppRegistry/renderApplication', () => {
describe('AppRegistry', () => {
describe('getApplication', () => {
const canUseDOM = ExecutionEnvironment.canUseDOM;
@@ -23,7 +23,9 @@ describe('AppRegistry/renderApplication', () => {
});
test('returns "element" and "getStyleElement"', () => {
const { element, getStyleElement } = getApplication(RootComponent, {});
AppRegistry.registerComponent('App', () => RootComponent);
const { element, getStyleElement } = AppRegistry.getApplication('App', {});
expect(element).toMatchSnapshot();
expect(ReactDOMServer.renderToStaticMarkup(getStyleElement())).toMatchSnapshot();
});
@@ -33,13 +35,16 @@ describe('AppRegistry/renderApplication', () => {
getStyleElement().props.dangerouslySetInnerHTML.__html;
// First "RootComponent" render
let app = getApplication(RootComponent, {});
AppRegistry.registerComponent('App1', () => RootComponent);
let app = AppRegistry.getApplication('App1', {});
render(app.element);
const first = getTextContent(app.getStyleElement);
// Next render is a different tree; the style sheet should be different
const styles = StyleSheet.create({ root: { borderWidth: 1234, backgroundColor: 'purple' } });
app = getApplication(() => <View style={styles.root} />, {});
const Component = () => <View style={styles.root} />;
AppRegistry.registerComponent('App2', () => Component);
app = AppRegistry.getApplication('App2', {});
render(app.element);
const second = getTextContent(app.getStyleElement);
@@ -51,11 +56,25 @@ describe('AppRegistry/renderApplication', () => {
// Final render is once again "RootComponent"; the style sheet should not
// be polluted by earlier rendering of a different tree
app = getApplication(RootComponent, {});
app = AppRegistry.getApplication('App1', {});
render(app.element);
const third = getTextContent(app.getStyleElement);
expect(first).toEqual(third);
});
});
describe('runApplication', () => {
test('callback after render', () => {
AppRegistry.registerComponent('App', () => RootComponent);
const callback = jest.fn();
const rootTag = document.createElement('div');
rootTag.id = 'react-root';
document.body.appendChild(rootTag);
AppRegistry.runApplication('App', { initialProps: {}, rootTag, callback });
expect(callback).toHaveBeenCalledTimes(1);
document.body.removeChild(rootTag);
});
});
});

View File

@@ -66,7 +66,8 @@ export default class AppRegistry {
componentProviderInstrumentationHook(componentProvider),
appParameters.initialProps || emptyObject,
appParameters.rootTag,
wrapperComponentProvider && wrapperComponentProvider(appParameters)
wrapperComponentProvider && wrapperComponentProvider(appParameters),
appParameters.callback,
)
};
return appKey;

View File

@@ -21,7 +21,8 @@ export default function renderApplication<Props: Object>(
RootComponent: ComponentType<Props>,
initialProps: Props,
rootTag: any,
WrapperComponent?: ?ComponentType<*>
WrapperComponent?: ?ComponentType<*>,
callback?: () => void
) {
invariant(rootTag, 'Expect to have a valid rootTag, instead got ', rootTag);
@@ -29,7 +30,8 @@ export default function renderApplication<Props: Object>(
<AppContainer WrapperComponent={WrapperComponent} rootTag={rootTag}>
<RootComponent {...initialProps} />
</AppContainer>,
rootTag
rootTag,
callback
);
}

View File

@@ -81,13 +81,15 @@ const AppRegistryScreen = () => (
<AppText>
Runs the application that was registered under <Code>appKey</Code>. The{' '}
<Code>appParameters</Code> must include the <Code>rootTag</Code> into which the
application is rendered, and optionally any <Code>initialProps</Code>.
application is rendered, and optionally any <Code>initialProps</Code> or render{' '}
<Code>callback</Code>
</AppText>
}
example={{
code: `AppRegistry.runApplication('MyApp', {
initialProps: {},
rootTag: document.getElementById('react-root')
rootTag: document.getElementById('react-root'),
callback: () => { console.log('React rendering has finished') }
})`
}}
name="static runApplication"