import React from 'react';
import {
StyleSheet,
View,
} from 'react-native';
import ReactMixin from 'react-mixin';
import TimerMixin from 'react-native-timer-mixin';
import PropTypes from 'prop-types';
import cloneReferencedElement from 'react-clone-referenced-element';
import LoadingOverlay from './LoadingOverlay';
import ErrorOverlay from './ErrorOverlay';
export default class LoadingContainer extends React.Component {
static LoadingOverlay = LoadingOverlay;
static ErrorOverlay = ErrorOverlay;
static propTypes = {
onLoadStartAsync: PropTypes.func.isRequired,
onReadyAsync: PropTypes.func.isRequired,
onError: PropTypes.func,
renderLoadingOverlay: PropTypes.func.isRequired,
renderErrorOverlay: PropTypes.func.isRequired,
};
static defaultProps = {
onReadyAsync: () => Promise.resolve(),
renderLoadingOverlay: props => ,
renderErrorOverlay: props => ,
};
state = {
isLoading: false,
};
componentDidMount() {
this._attemptLoadAsync().done();
}
render() {
let loadingOverlay = cloneReferencedElement(
this.props.renderLoadingOverlay({}),
{ ref: component => { this._loadingOverlay = component; } }
);
let errorOverlay = cloneReferencedElement(
this.props.renderErrorOverlay({onRetryLoad: this._attemptLoadAsync}),
{ ref: component => { this._errorOverlay = component; } }
);
return (
{this.props.children}
{loadingOverlay}
{errorOverlay}
);
}
showLoadingOverlay = () => {
this._errorOverlay.hideOverlay();
this._loadingOverlay.showOverlay();
}
reloadAsync = async () => {
return this._attemptLoadAsync();
}
_attemptLoadAsync = async () => {
if (this.state.isLoading) {
return;
}
this.setState({ isLoading: true });
this.showLoadingOverlay();
let result;
try {
result = await this.props.onLoadStartAsync();
} catch (e) {
this._handleError(e);
return;
}
await this.props.onReadyAsync(result);
this._loadingOverlay && this._loadingOverlay.fadeOverlay();
this.setState({ isLoading: false });
}
_handleError = (e) => {
this.setState({ isLoading: false });
this._errorOverlay && this._errorOverlay.showOverlay();
this._loadingOverlay && this._loadingOverlay.hideOverlay();
if (this.props.onError) {
this.props.onError(e);
}
}
}
ReactMixin(LoadingContainer.prototype, TimerMixin);
const styles = StyleSheet.create({
container: {
position: 'absolute',
top: 0,
bottom: 0,
left: 0,
right: 0,
},
});