-
-
Save kachar/dae47c4f44f3080771cc956e039c439a to your computer and use it in GitHub Desktop.
A route change indicator for Next.js using React hooks.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#nprogress { | |
position: fixed; | |
left: 0; | |
top: 0; | |
right: 100%; | |
z-index: 2; | |
height: 3px; | |
background-color: $primary; | |
box-shadow: 0 1px 8px rgba(0, 0, 0, .1); | |
opacity: 0; | |
transition-property: right, opacity; | |
transition-duration: 0s; | |
pointer-events: none; | |
&.loading { | |
right: 5%; | |
opacity: 1; | |
transition-timing-function: cubic-bezier(.075, .82, .165, 1); | |
transition-duration: 8s, 0s; | |
} | |
&.done { | |
right: 0; | |
transition-duration: 250ms; | |
transition-delay: 0s, 250ms; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import cn from 'classnames' | |
import Router from 'next/router' | |
import React, { useState } from 'react' | |
const DONE_DURATION = 250 | |
export default function RouteIndicator() { | |
const [loading, setLoading] = useState(false) | |
const [timeoutId, setTimeoutId] = useState<ReturnType<typeof setTimeout>>() | |
const onLoad = () => setLoading(true) | |
const onDone = () => { | |
setLoading(false) | |
const timeoutId = setTimeout(() => { | |
setTimeoutId(undefined) | |
setLoading(false) | |
}, DONE_DURATION) | |
setTimeoutId(timeoutId) | |
} | |
// Register route change event handlers | |
React.useEffect(() => { | |
Router.events.on('routeChangeStart', onLoad) | |
Router.events.on('routeChangeComplete', onDone) | |
Router.events.on('routeChangeError', onDone) | |
return () => { | |
Router.events.off('routeChangeStart', onLoad) | |
Router.events.off('routeChangeComplete', onDone) | |
Router.events.off('routeChangeError', onDone) | |
} | |
}) | |
React.useEffect(() => { | |
return () => timeoutId && clearTimeout(timeoutId) | |
}, [timeoutId]) | |
return ( | |
<div | |
id="nprogress" | |
className={cn({ | |
loading, | |
done: !loading, | |
})} | |
/> | |
) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment