diff --git a/app/soapbox/features/ui/components/bundle.js b/app/soapbox/features/ui/components/bundle.tsx similarity index 68% rename from app/soapbox/features/ui/components/bundle.js rename to app/soapbox/features/ui/components/bundle.tsx index 11622ec19..55f6478bc 100644 --- a/app/soapbox/features/ui/components/bundle.js +++ b/app/soapbox/features/ui/components/bundle.tsx @@ -1,21 +1,29 @@ -import PropTypes from 'prop-types'; import React from 'react'; const emptyComponent = () => null; const noop = () => { }; -class Bundle extends React.PureComponent { +interface BundleProps { + fetchComponent: () => Promise, + loading: React.ComponentType, + error: React.ComponentType<{ onRetry: (props: BundleProps) => void }>, + children: (mod: any) => React.ReactNode, + renderDelay?: number, + onFetch: () => void, + onFetchSuccess: () => void, + onFetchFail: (error: any) => void, +} - static propTypes = { - fetchComponent: PropTypes.func.isRequired, - loading: PropTypes.func, - error: PropTypes.func, - children: PropTypes.func.isRequired, - renderDelay: PropTypes.number, - onFetch: PropTypes.func, - onFetchSuccess: PropTypes.func, - onFetchFail: PropTypes.func, - } +interface BundleState { + mod: any, + forceRender: boolean, +} + +/** Fetches and renders an async component. */ +class Bundle extends React.PureComponent { + + timeout: NodeJS.Timeout | undefined; + timestamp: Date | undefined; static defaultProps = { loading: emptyComponent, @@ -37,7 +45,7 @@ class Bundle extends React.PureComponent { this.load(this.props); } - componentWillReceiveProps(nextProps) { + componentWillReceiveProps(nextProps: BundleProps) { if (nextProps.fetchComponent !== this.props.fetchComponent) { this.load(nextProps); } @@ -49,7 +57,7 @@ class Bundle extends React.PureComponent { } } - load = (props) => { + load = (props: BundleProps) => { const { fetchComponent, onFetch, onFetchSuccess, onFetchFail, renderDelay } = props || this.props; const cachedMod = Bundle.cache.get(fetchComponent); @@ -88,10 +96,10 @@ class Bundle extends React.PureComponent { render() { const { loading: Loading, error: Error, children, renderDelay } = this.props; const { mod, forceRender } = this.state; - const elapsed = this.timestamp ? (new Date() - this.timestamp) : renderDelay; + const elapsed = this.timestamp ? ((new Date()).getTime() - this.timestamp.getTime()) : renderDelay!; if (mod === undefined) { - return (elapsed >= renderDelay || forceRender) ? : null; + return (elapsed >= renderDelay! || forceRender) ? : null; } if (mod === null) { diff --git a/app/soapbox/features/ui/containers/bundle_container.js b/app/soapbox/features/ui/containers/bundle_container.tsx similarity index 74% rename from app/soapbox/features/ui/containers/bundle_container.js rename to app/soapbox/features/ui/containers/bundle_container.tsx index b12e29a43..12e4b3787 100644 --- a/app/soapbox/features/ui/containers/bundle_container.js +++ b/app/soapbox/features/ui/containers/bundle_container.tsx @@ -3,14 +3,16 @@ import { connect } from 'react-redux'; import { fetchBundleRequest, fetchBundleSuccess, fetchBundleFail } from '../../../actions/bundles'; import Bundle from '../components/bundle'; -const mapDispatchToProps = dispatch => ({ +import type { AppDispatch } from 'soapbox/store'; + +const mapDispatchToProps = (dispatch: AppDispatch) => ({ onFetch() { dispatch(fetchBundleRequest()); }, onFetchSuccess() { dispatch(fetchBundleSuccess()); }, - onFetchFail(error) { + onFetchFail(error: any) { dispatch(fetchBundleFail(error)); }, });