AppContainer.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /**
  2. * Copyright (c) Facebook, Inc. and its affiliates.
  3. *
  4. * This source code is licensed under the MIT license found in the
  5. * LICENSE file in the root directory of this source tree.
  6. *
  7. * @format
  8. * @flow
  9. */
  10. 'use strict';
  11. const EmitterSubscription = require('../vendor/emitter/EmitterSubscription');
  12. const PropTypes = require('prop-types');
  13. const RCTDeviceEventEmitter = require('../EventEmitter/RCTDeviceEventEmitter');
  14. const React = require('react');
  15. const RootTagContext = require('./RootTagContext');
  16. const StyleSheet = require('../StyleSheet/StyleSheet');
  17. const View = require('../Components/View/View');
  18. type Context = {rootTag: number, ...};
  19. type Props = $ReadOnly<{|
  20. children?: React.Node,
  21. fabric?: boolean,
  22. rootTag: number,
  23. showArchitectureIndicator?: boolean,
  24. WrapperComponent?: ?React.ComponentType<any>,
  25. internal_excludeLogBox?: ?boolean,
  26. |}>;
  27. type State = {|
  28. inspector: ?React.Node,
  29. mainKey: number,
  30. hasError: boolean,
  31. |};
  32. class AppContainer extends React.Component<Props, State> {
  33. state: State = {
  34. inspector: null,
  35. mainKey: 1,
  36. hasError: false,
  37. };
  38. _mainRef: ?React.ElementRef<typeof View>;
  39. _subscription: ?EmitterSubscription = null;
  40. static getDerivedStateFromError: any = undefined;
  41. static childContextTypes:
  42. | any
  43. | {|rootTag: React$PropType$Primitive<number>|} = {
  44. rootTag: PropTypes.number,
  45. };
  46. getChildContext(): Context {
  47. return {
  48. rootTag: this.props.rootTag,
  49. };
  50. }
  51. componentDidMount(): void {
  52. if (__DEV__) {
  53. if (!global.__RCTProfileIsProfiling) {
  54. this._subscription = RCTDeviceEventEmitter.addListener(
  55. 'toggleElementInspector',
  56. () => {
  57. const Inspector = require('../Inspector/Inspector');
  58. const inspector = this.state.inspector ? null : (
  59. <Inspector
  60. inspectedView={this._mainRef}
  61. onRequestRerenderApp={updateInspectedView => {
  62. this.setState(
  63. s => ({mainKey: s.mainKey + 1}),
  64. () => updateInspectedView(this._mainRef),
  65. );
  66. }}
  67. />
  68. );
  69. this.setState({inspector});
  70. },
  71. );
  72. }
  73. }
  74. }
  75. componentWillUnmount(): void {
  76. if (this._subscription != null) {
  77. this._subscription.remove();
  78. }
  79. }
  80. render(): React.Node {
  81. let logBox = null;
  82. if (__DEV__) {
  83. if (
  84. !global.__RCTProfileIsProfiling &&
  85. !this.props.internal_excludeLogBox
  86. ) {
  87. const LogBoxNotificationContainer = require('../LogBox/LogBoxNotificationContainer')
  88. .default;
  89. logBox = <LogBoxNotificationContainer />;
  90. }
  91. }
  92. let innerView = (
  93. <View
  94. collapsable={!this.state.inspector}
  95. key={this.state.mainKey}
  96. pointerEvents="box-none"
  97. style={styles.appContainer}
  98. ref={ref => {
  99. this._mainRef = ref;
  100. }}>
  101. {this.props.children}
  102. </View>
  103. );
  104. const Wrapper = this.props.WrapperComponent;
  105. if (Wrapper != null) {
  106. innerView = (
  107. <Wrapper
  108. fabric={this.props.fabric === true}
  109. showArchitectureIndicator={
  110. this.props.showArchitectureIndicator === true
  111. }>
  112. {innerView}
  113. </Wrapper>
  114. );
  115. }
  116. return (
  117. <RootTagContext.Provider value={this.props.rootTag}>
  118. <View style={styles.appContainer} pointerEvents="box-none">
  119. {!this.state.hasError && innerView}
  120. {this.state.inspector}
  121. {logBox}
  122. </View>
  123. </RootTagContext.Provider>
  124. );
  125. }
  126. }
  127. const styles = StyleSheet.create({
  128. appContainer: {
  129. flex: 1,
  130. },
  131. });
  132. if (__DEV__) {
  133. if (!global.__RCTProfileIsProfiling) {
  134. const LogBox = require('../LogBox/LogBox');
  135. LogBox.install();
  136. }
  137. }
  138. module.exports = AppContainer;