UNPKG

@eolme/vma-router

Version:
49 lines (48 loc) 2.19 kB
import React from 'react'; import { useContext, useState, useRef, useEffect, useCallback, timers } from '@eolme/vma-engine'; import { RouterContext } from '../components/RouterContext'; import { error } from '../utils/report'; const MAGIC_UPDATE_INTERVAL = 650; export function withTransitionRouter(Component) { const withTransitionRouter = (props) => { /* eslint-disable react-hooks/rules-of-hooks */ const router = useContext(RouterContext); if (!router) { error('Missing router context!'); return null; } const lastUpdateRouteAt = useRef(0); const updateTimer = useRef(0); const updateCallback = useRef(null); const [route, setRoute] = useState(router.history.route); useEffect(() => { const fn = (event) => { const diff = Date.now() - lastUpdateRouteAt.current; if (diff >= MAGIC_UPDATE_INTERVAL) { lastUpdateRouteAt.current = Date.now(); setRoute(event.next); } else { timers.clearTimeout(updateTimer.current); updateCallback.current = () => { lastUpdateRouteAt.current = Date.now(); setRoute(event.next); updateCallback.current = null; }; updateTimer.current = timers.setTimeout(updateCallback.current, MAGIC_UPDATE_INTERVAL - diff); } }; router.history.on('update', fn); return () => { router.history.off('update', fn); }; }, [router]); const onTransitionEnd = useCallback(() => { lastUpdateRouteAt.current = 0; }, []); return (React.createElement(Component, Object.assign({}, props, { onTransitionEnd: onTransitionEnd, route: route }))); }; const displayName = Component.displayName || Component.name || 'Component'; withTransitionRouter.displayName = `withTransitionRouter(${displayName})`; return withTransitionRouter; }