import { Router } from 'next/router' import React from 'react' import { buildClassName } from '../Util' import css from './Loader.module.styl' interface Props { /** * The new Percentage (if you calculate it yourself) */ percent?: number /** * Auto random loader */ auto?: { /** * the minimum and maximum interval between two increment */ interval: [number, number] /** * the minimum and maximum incrementation (MUST be an integer) */ increment: [number, number] } } interface State { percent?: number } /** * Display a simple loading animation at the top of the page * * @version 1.0.0 */ export default class Loader extends React.Component { public state: State = {} private interval?: NodeJS.Timeout public componentDidMount() { if (this.props.auto) { Router.events.on('routeChangeComplete', this.routeChangeComplete) Router.events.on('routeChangeStart', this.routeChangeStart) } } public componentWillUnmount() { if (this.props.auto) { Router.events.off('routeChangeComplete', this.routeChangeComplete) Router.events.off('routeChangeStart', this.routeChangeStart) } } public render = () => (
) private routeChangeComplete = () => { if (this.interval) { clearTimeout(this.interval) this.interval = undefined } this.setState({percent: 100}) } private routeChangeStart = () => { if (this.interval) { clearTimeout(this.interval) } this.setState({percent: 0}, () => { if (!this.props.auto) {return} this.interval = setTimeout(this.timeoutFn, this.randomInt(this.props.auto.interval[0], this.props.auto.interval[1])) }) } private timeoutFn = () => { if (!this.props.auto) {return} const p = this.state.percent || 0 this.setState({ percent: Math.min( 99, p >= 80 ? p + Math.random() : p + this.randomInt(this.props.auto.increment[0], this.props.auto.increment[1]) ) }) this.interval = setTimeout(this.timeoutFn, this.randomInt(this.props.auto.interval[0], this.props.auto.interval[1])) } private randomInt(min = 0, max = 10) { min = Math.ceil(min) max = Math.floor(max) return Math.floor(Math.random() * (max - min + 1)) + min } }