I'm currently experiencing a problem with my post/:id
routes where next flashes the 404
page before successfully rendering my component. At first, I thought this was a redux related issues as my post/id
pages are checking the app state to filter
whichever component should be shown using shallow routing.
After discussing this in the slack channel, I added another API call that would retrieve each blog post but quickly found that I still encountered the same issue. I know that this has happened for at least one other developer so i'm wondering if anyone can point me in the right direction? I'm trying to finish up this personal portfolio I built with next.
Below, you can see exactly what's happening. Everything looks A1 except for that 404 that blinks whenever a specific post is rendered.
The benefits i've gained are tremendous however there have been some minor issues like this one that have got me a little puzzled 馃 . Anyways, let me know if I can provide any additional info. Thanks 馃槃
Same issue +1
How are you rendering the Link component to that url? Are you using <Link href="/post/1">
or <Link href="/post?id=1" as="/post/1">
?
Currently, i'm using <Link prefetch href={
/blog/${x.id}} />
. I've tried <Link prefetch href={
/blog/${x.id}} as={
/blog/${x.id}} />
in the past and just plugged it in again. Still having the same issue.
Your href
and as
props shouldn't be the same, href
is the real url, if you have pages/blog.js
and receive id as a query then href
should be /blog?id=${x.id}
and as
is your pretty custom url in this case /blog/${x.id}
.
@sergiodxa I just put this code in place.
<Link href={`/blog?id=${x.id}`} as={`blog/${x.id}`}>
<a>Read Post</a>
</Link>
Now it's re-rendering the /blog
page on every click while adding the id
to the URL.
@tgrecojs Hope this code snippet helps
const href = `/journal?home=${this.state.article.path[0]}&articlePath=${this.state.article.path[1]}&file=${this.state.article.path[2]}`
const as = `/journal/${this.state.article.path[0]}/${this.state.article.path[1]}/${this.state.article.path[2]}`
Would render as https://www.someURL.com/journal/articlePath/morePath/evenMorePath
I understand how the path's work @ugiacoman that's not my issue. If you can see in my initial report, i'm successfully navigating to each blog post however the issue is that weird 404
error.
@tgrecojs I made an example repo https://github.com/sergiodxa/next-custom-query (deployed: https://next-custom-query.now.sh/blog), there you can see how to use the custom urls without reloading and a 404 using the next/link
component as described above.
@sergiodxa I appreciate that! I just checked it out and added some async calls to the google blogger API which is what i'm currently pinging. Below, you can see how it's navigating to the route but it's not correctly loading the data.
Removed gif
Now this issue is a slightly different reproduction of this issue than what is shown in my first comment. When I first ran into this problem, I thought it was because I was using redux and that the application state wasn't carrying over the post/id
pages. This led me to integrating a new API call for each post, just like I integrated in the app you've created, however I still found that I had the same problem.
I was running into some trouble forking your repo 馃槵 so you can find my code here -> https://github.com/tgrecojs/next-custom-query-async. Let me know you're thoughts! 馃槃
It looks you're getting a 400, when forking your project I'm getting that same error with a usageLimits error message. That's probably why you're getting that error.
Ok. I'll investigate a little further tomorow but I want to point out that the video I posted when opening the issue is not making an API request on the /blog/:id
route. Instead, it's filtering the posts from my redux store which is collected on the /blog
route transition so that couldn't be the reason I arrived at this issue. I only implemented the 2nd API call (made inside blog/:id
) as I thought it had something to do with my redux-store but found myself receiving the same error but that's not the current implementation in my code.
As soon as I realized that it threw the same bug, I switched back to using only one API call (Inside /blog
) and then filtering for the necessary blog post by id.
@sergiodxa I can confirm that it's not usage limits. You'll see that the id
isn't always being correctly passed to the /blog/:id
route... I've attached the 400
error that i'm receiving. You'll see that id
is undefined and (in this instance) it seems to be why i'm getting the error.
I've included another video below. Any thoughts as to why it may be behaving this way? I haven't changed the <Link />
tags inside this repository yet still having the issue 馃槵 .
Again, I want to point out that the video above shows my reproducing the error inside of the example repo you've created - https://github.com/sergiodxa/next-custom-query.
I'm also getting 404 flashing without any custom routes. Just a file called orders.js
in pages/
with this code:
import { Component } from 'react';
class Orders extends Component {
render() {
return (
<div>
<h2>My Orders</h2>
</div>
)
}
}
export default Orders;
Seems like a pretty critical issue 馃槄
I tried to replicate it and is because the trailing slash at the end of the URL, if you go to /orders
you don't see the 404 but if you go to /orders/
then you see that 404 flashing before the content, this happens either in dev and production mode.
Ah this is a known issue. https://github.com/zeit/next.js/issues/1189
My issue didn't arise due to a trailing slash so there's got to be something else, right?
I've made some changes in my code and i've deployed 2 different versions, one using prefetch
and one that doesn't. I want to note that neither application is now able to successfully load a post/:id
route.
One noticed that when I use prefetch
in the link, it now throws a Page Does Not Exist Error
when rendering the links for each blog post. You can see a screenshot of my console below.
When I don't use prefetch, the error shown above no longer exists but it does not render the application. When I initially posted this issue, my component was initializing my blog for each post/:id
component. I've since removed that since now individual posts never render.
Let me know if I can provide any more info that can help diagnose this issue. 馃
@tgrecojs I have almost the exact same problem. prefetch
did not solve my problem.
The behavior I get is the following:
I hope this can help debug the issue!
Extra info: Node v6.10.3
, Chrome Version 60.0.3112.90
EDIT: Deployed the app so you guys can test it https://datahub.now.sh/, it's the link /@[username] that has this behaviour
@Theo- the href in that next/link is user?id=1
, can you try /user?id=1
instead? I think the 404 is because Next.js is trying to get to /current/path/user?id=1
instead of /user?id=1
, but when the page reload it works fine because of the server render.
@sergiodxa that did it. Thank you!
@tgrecojs I had the same flashing 404 behavior. In my case, I had a link with an environment variable which didn't work on the client, therefore the 404 but on the server, it worked. Solved it with https://medium.com/the-tech-bench/next-js-environment-variables-d2f6ea1a1dca.
@andreaskeller hmmm ok i'll check it out. thank you this!!! i'm currently ONLY using my .env variables when the app is server render. I have a higher order component that uses dotenv to check to see it's CSR or SSR, if it is SSR I then dispatch the function needed to log the blog posts.
yeah, I've already got my variables working fine. I'm rendering that my /blog
route using an HOC that gets my BLOGGER_API_KEY
so it's working in those examples.... my /post/:id
s child pages aren't using any env variables.
going to do some more digging, hopefully i can get to the bottom of it!
Its seems like most of the issues here are fixed. I'll work on this issue as well https://github.com/zeit/next.js/issues/1189
I'm closing this now. But If we need to do something in the core, let me know.
@sergiodxa as per our conversation last night, i've created the lil barebones app showing my issue. Let me know if you have any questions about it! I would be more than happy to fill you in on everything that is going on with it! 馃槃
It's not fixed.
i have the same problem but without any custom routes. I have /pages/pipeline.tsx and /pipeline url works just fine while /pipeline/ flashes 404 and then tries to load my page without calling "getInitialProps" called (since it was 404 on the server!).
@ex3ndr Not sure if this will fix the problem, but I had a similar issue and this cured it.
https://github.com/zeit/next.js#disabling-file-system-routing
Chances are next is trying to pull off the fileSystem before your custom route is hit.
@moaxaca I have solved the same way since i was needed to have my own custom routing - i just disabled next's one altogether.
I'm seeing this issue as well. @moaxaca's solution didn't work for me. What did was to use any Link
component, but instead opt for using next-routes's pushRoute
method.
Basic example:
import { connect } from 'react-redux'
import { Router } from '../routes'
// ----
export default class Link extends React.Component {
handleClick(evt, url) {
evt.preventDefault()
Router.pushRoute(url)
}
render() {
const { url, title } = this.props
return (
<a href={ url} onClick={ (evt) => this.handleClick(evt, url) }>{title}</a>
)
}
}
This seems to figure it out and I don't see the Error Flashing. But it feels a bit quickfixy.
save issue
I got the same issue before and I was able to solve it. I'm using an express server set up. I found out that the reason why the 404 page flashes before loading to the right page is because my page slug doesn't match my component name.
When I have this code the 404 flashes:
server.get('/search', (req, res) => {
const actualPage = '/search_results'
const queryParams = { filters: req.query }
app.render(req, res, actualPage, queryParams)
})
Note that the /search
and my actualPage
values are different.
The 404 flashes disappears when I rename my component & the actualPage
values to be the same as my page slug which is search
. See working code below:
server.get('/search', (req, res) => {
const actualPage = '/search'
const queryParams = { filters: req.query }
app.render(req, res, actualPage, queryParams)
})
Now both are using /search
.
Sorry for my english guys.
it may be a good idea to check you next.config.js
useFileSystemPublicRoutes
property. If it is false, that means you must define all the route handlers in server.js yourself.
This fixes the flashing 404 for me:
<Link href="/somepage?id=value" as="/somepage/value">
server.get("/somepage/:id", (req, res) => {
return app.render(req, res, "/maps", { id: req.params.id })
})
const { id } = this.props.url.query
So to answer this one once and for all:
href
=> path inside of the pages
directory + the querystring
as
=> rendered in the browser url bar
Example:
You have a url called /products/:id
pages/product.js
export default class extends React.Component {
static async getInitialProps({query}) {
console.log('SLUG', query.slug)
return {}
}
render() {
return <h1>The product page</h1>
}
}
/products/:id
to pages/product.js
and provide id
as part of query
in getInitialProps:server.get("/products/:slug", (req, res) => {
return app.render(req, res, "/product", { slug: req.params.slug })
})
next/link
like this:<Link href="/product?slug=something" as="/products/something">
The reason you have to explicitly provide the href
and as
is that Next.js is not aware of any other pages on the client side. We don't send a manifest of all pages to the client side and subsequent routes get lazy-loaded, which is scalable.
There is a community package that abstracts away providing href
and as
by sending a pre-defined manifest of all routes, note that we recommend not sending a full manifest of all possible routes as not doing this is more scaleable
https://github.com/fridays/next-routes
Also, note that rendering 404 is no longer the default behavior of Next.js. Instead, we reload the page for the Zones feature.
Thanks Tim, totally clear explanation!
@timneutkens
If the Link's href and as. I pass the different value. How could I get href
's value and as
's value.
I test me demo. I think req.params.slug will be as
's value. Then how could I get href
's value.
@timneutkens You saved me I don't know how many hours of painful search for my issue :D
How are you rendering the Link component to that url? Are you using
<Link href="/post/1">
or<Link href="/post?id=1" as="/post/1">
?
You should put this in doc. :joy:
@sergiodxa
So to answer this one once and for all:
href
=> path inside of thepages
directory + the querystring
as
=> rendered in the browser url barExample:
You have a url called
/products/:id
- You created
pages/product.js
export default class extends React.Component { static async getInitialProps({query}) { console.log('SLUG', query.slug) return {} } render() { return <h1>The product page</h1> } }
- You add the route to express or any other server, this is _only_ for SSR. What this will do is route the url
/products/:id
topages/product.js
and provideid
as part ofquery
in getInitialProps:server.get("/products/:slug", (req, res) => { return app.render(req, res, "/product", { slug: req.params.slug }) })
- For client side routing you use
next/link
like this:<Link href="/product?slug=something" as="/products/something">
The reason you have to explicitly provide the
href
andas
is that Next.js is not aware of any other pages on the client side. We don't send a manifest of all pages to the client side and subsequent routes get lazy-loaded, which is scalable.There is a community package that abstracts away providing
href
andas
by sending a pre-defined manifest of all routes, note that we recommend not sending a full manifest of all possible routes as not doing this is more scaleablehttps://github.com/fridays/next-routes
Also, note that rendering 404 is no longer the default behavior of Next.js. Instead, we reload the page for the Zones feature.
what I can do if I only have an array of list header like:
[
home: '/home',
about:'/about',
post: 'post/:post_id?'
]
.
In next I only get as's
value, but how about href
? Thanks :D
What if you're using router.push()
instead of <Link>
how can you achieve the same results?
@justinmchase I just had the same problem. Check Next Router documentation if you haven't already.
You can use it as Router.push(url, as, options)
:
Router.push('/post/[pid]', '/post/abc')
@timneutkens I would like to host my next.js app on ZEIT.now but that doesn't have an option to run an express server. Do I loose my pretty urls now and can only do param=value¶m=value
or is there another way? The example Sergio posted doesn't look promising
I tried dynamic routes but now my single page application is broken and links such as:
<Link href={`/integration?slug=${slug}`} as={`/integration/${slug}`}>
now cause a full page reload because http://localhost:8080/_next/static/development/pages/integration.js returns a 404 not found.
@timneutkens I would like to host my next.js app on ZEIT.now but that doesn't have an option to run an express server. Do I loose my pretty urls now and can only do
param=value¶m=value
or is there another way? The example Sergio posted doesn't look promising
You don't need a custom server for dynamic routes, see https://nextjs.org/docs/routing/dynamic-routes
@timneutkens Thank you for your fast reply, I tried dynamic routes but will break single page application (see update). Running locally with next
in my package.json script in dev mode.
Solved it by having a pages/integration/index.js
with the code and a pages/integration/[slug].js
with:
import ProductDetailPage from './index'
export default ProductDetailPage
The correct way to do what you outlined is to create pages/integration/[slug].js
And link to it in this way:
<Link href={`/integration/[slug]`} as={`/integration/${slug}`}>
Hi can I ask why when i call this one
Router.push( '/about?id=1234','/about')
the id cant be retrieve, and the page i am using is [...index].js which is a multi dynamic catch all page, but if I direct to other page that is not dynamic one it can work properly example car.js push to vehicle.js..
Is there a better way where i can push to my dynamic catch all page and then mask the id and still able to retrieve it..?
Most helpful comment
So to answer this one once and for all:
href
=> path inside of thepages
directory + the querystringas
=> rendered in the browser url barExample:
You have a url called
/products/:id
pages/product.js
/products/:id
topages/product.js
and provideid
as part ofquery
in getInitialProps:next/link
like this:The reason you have to explicitly provide the
href
andas
is that Next.js is not aware of any other pages on the client side. We don't send a manifest of all pages to the client side and subsequent routes get lazy-loaded, which is scalable.There is a community package that abstracts away providing
href
andas
by sending a pre-defined manifest of all routes, note that we recommend not sending a full manifest of all possible routes as not doing this is more scaleablehttps://github.com/fridays/next-routes
Also, note that rendering 404 is no longer the default behavior of Next.js. Instead, we reload the page for the Zones feature.