1 |
|
2 | import React from 'react';
|
3 | import { EventEmitter } from 'fbemitter';
|
4 | import NativeAppLoading from './AppLoadingNativeWrapper';
|
5 |
|
6 | type Props =
|
7 | | {
|
8 | startAsync: () => Promise<any>,
|
9 | onError?: (error: Error) => void,
|
10 | onFinish: () => void,
|
11 | }
|
12 | | {
|
13 | startAsync: null,
|
14 | onError: null,
|
15 | onFinish: null,
|
16 | };
|
17 |
|
18 | export default class AppLoading extends React.Component<Props> {
|
19 | _isMounted: boolean;
|
20 |
|
21 | componentDidMount() {
|
22 | this._isMounted = true;
|
23 | _emitEvent('componentDidMount');
|
24 |
|
25 |
|
26 |
|
27 | if (this.props.startAsync) {
|
28 |
|
29 | this._startLoadingAppResourcesAsync().done();
|
30 | }
|
31 | }
|
32 |
|
33 | componentWillUnmount() {
|
34 | this._isMounted = false;
|
35 | _emitEvent('componentWillUnmount');
|
36 | }
|
37 |
|
38 | _startLoadingAppResourcesAsync = async () => {
|
39 | if (!this.props.onFinish) {
|
40 | throw new Error(
|
41 | 'AppLoading onFinish prop is required if startAsync is provided'
|
42 | );
|
43 | }
|
44 |
|
45 | try {
|
46 | await this.props.startAsync();
|
47 | } catch (e) {
|
48 | if (!this._isMounted) return;
|
49 |
|
50 | if (this.props.onError) {
|
51 | this.props.onError(e);
|
52 | } else {
|
53 | throw e;
|
54 | }
|
55 | } finally {
|
56 | if (!this._isMounted) return;
|
57 |
|
58 |
|
59 |
|
60 | if (this.props.onFinish) {
|
61 | this.props.onFinish();
|
62 | }
|
63 | }
|
64 | };
|
65 |
|
66 | render() {
|
67 | return <NativeAppLoading />;
|
68 | }
|
69 | }
|
70 |
|
71 | let _lifecycleEmitter: ?EventEmitter;
|
72 | function _emitEvent(event: string) {
|
73 | if (_lifecycleEmitter) {
|
74 | _lifecycleEmitter.emit(event);
|
75 | }
|
76 | }
|
77 |
|
78 | export function getAppLoadingLifecycleEmitter() {
|
79 | if (!_lifecycleEmitter) {
|
80 | _lifecycleEmitter = new EventEmitter();
|
81 | }
|
82 | return _lifecycleEmitter;
|
83 | }
|
84 |
|
\ | No newline at end of file |