/** * @file LazyComponent * @description * @author fex */ import React from 'react'; // @ts-ignore import VisibilitySensor from 'react-visibility-sensor'; import Spinner from './Spinner'; export interface LazyComponentProps { component?: React.ReactType; getComponent?: () => Promise; placeholder?: React.ReactNode; unMountOnHidden?: boolean; childProps?: object; visiblilityProps?: object; [propName: string]: any; } export interface LazyComponentState { visible: boolean; component?: React.ReactType; } export default class LazyComponent extends React.Component< LazyComponentProps, LazyComponentState > { static defaultProps = { placeholder: , unMountOnHidden: false, partialVisibility: true }; mounted: boolean = false; constructor(props: LazyComponentProps) { super(props); this.handleVisibleChange = this.handleVisibleChange.bind(this); this.state = { visible: false, component: props.component as React.ReactType }; } componentWillMount() { this.mounted = true; } componentWillUnmount() { this.mounted = false; } handleVisibleChange(visible: boolean) { this.setState({ visible: visible }); if (!visible || this.state.component || !this.props.getComponent) { return; } this.props .getComponent() .then( component => this.mounted && typeof component === 'function' && this.setState({ component: component }) ) .catch( reason => this.mounted && this.setState({ component: () => (
{String(reason)}
) }) ); } render() { const { placeholder, unMountOnHidden, childProps, visiblilityProps, partialVisibility, children, ...rest } = this.props; const {visible, component: Component} = this.state; // 需要监听从可见到不可见。 if (unMountOnHidden) { return (
{Component && visible ? ( ) : children && visible ? ( children ) : ( placeholder )}
); } if (!visible) { return (
{placeholder}
); } else if (Component) { // 只监听不可见到可见,一旦可见了,就销毁检查。 return ; } else if (children) { return children; } return
{placeholder}
; } }