Next.js router.isReady never set to true on custom 404 page
See original GitHub issueVerify canary release
- I verified that the issue exists in Next.js canary release
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 21.4.0: Fri Mar 18 00:46:32 PDT 2022; root:xnu-8020.101.4~15/RELEASE_ARM64_T6000
Binaries:
Node: 17.7.2
npm: 8.5.5
Yarn: 1.22.17
pnpm: N/A
Relevant packages:
next: 12.1.5-canary.4
react: 17.0.2
react-dom: 17.0.2
What browser are you using? (if relevant)
Safari 15.4 (17613.1.17.1.13)
How are you deploying your application? (if relevant)
next dev
Describe the Bug
The Next.js router object contains a boolean value router.isReady
, which according to docs indicates:
Whether the router fields are updated client-side and ready for use. Should only be used inside of useEffect methods and not for conditionally rendering on the server. See related docs for use case with automatically statically optimized pages
We are using this in a withSSRLoadingIndicator
HoC that checks inside an useEffect
hook that if the router is ready, render page component, and else render a full-screen loading indicator. This allows us to deploy certain pages as small static files, which only load client-side, while other pages can use the full getServerSideProps
method and render what they need directly. With the HoC, we don’t have to check if the router.query
object is populated, because the page component will receive the data on its first render (because then router.isReady = true
).
This HoC works nicely on all other pages expect our custom 404 page, and after a bit of debugging it seems that the Router instance simply never sets router.isReady = true
.
Expected Behavior
I would expect the custom 404 to also receive router.isReady = true
on the client-side.
To Reproduce
Create a Next.js page src/pages/index.js
with code like this:
import { useRouter } from 'next/router'
import React, { useEffect, useState } from 'react'
export default () => {
const router = useRouter()
const [state, setState] = useState(false)
useEffect(() => {
setState(router.isReady)
}, [router.isReady])
return <p>{state === true ? 'Router is ready' : 'Router is not ready'}</p>
}
When opening the page in your browser, http://localhost:3000/, you will see:
Router is not ready
on the first renderRouter is ready
on the second render
Copy the same page component as src/pages/404.js
, open http://localhost:3000/404, and you will instead see:
Router is not ready
on the first render- …there will not be a second render at all
Issue Analytics
- State:
- Created a year ago
- Reactions:16
- Comments:7 (2 by maintainers)
Top GitHub Comments
I am able to reproduce this bug the way @iiroj described. Do we have any progress on this bug? It hardly breaks my website’s functionality
I found out that
router.isReady
works as expected when reusing the built-in error by creating custom_error
page.