Next.js: Route personnalisée `post/`id` clignotant 404 avant le rendu final de la page.

Créé le 22 août 2017  ·  47Commentaires  ·  Source: vercel/next.js

Je rencontre actuellement un problème avec mes routes post/:id où la page 404 clignote ensuite avant de rendre mon composant avec succès. Au début, je pensais qu'il s'agissait d'un problème lié à la redux car mes pages post/id vérifiaient l'état de l'application à filter quel

Après en avoir discuté dans le canal slack, j'ai ajouté un autre appel d'API qui récupèrerait chaque article de blog, mais j'ai rapidement constaté que je rencontrais toujours le même problème. Je sais que cela s'est produit pour au moins un autre développeur, donc je me demande si quelqu'un peut m'orienter dans la bonne direction ? J'essaie de terminer ce portfolio personnel avec lequel j'ai construit ensuite.

Ci-dessous, vous pouvez voir exactement ce qui se passe. Tout ressemble à A1 sauf ce 404 qui clignote chaque fois qu'un message spécifique est rendu.

next.js blog post err

Les avantages que j'ai gagnés sont énormes, mais il y a eu quelques problèmes mineurs comme celui-ci qui m'ont un peu perplexe 🤔 . Quoi qu'il en soit, laissez-moi savoir si je peux fournir des informations supplémentaires. Merci

Commentaire le plus utile

Alors pour répondre à celui-ci une bonne fois pour toutes :

href => chemin à l'intérieur du répertoire pages + la chaîne de requête
as => rendu dans la barre d'URL du navigateur

Exemple:

Vous avez une URL appelée /products/:id

  1. Vous avez créé 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>
  }
}
  1. Vous ajoutez la route vers express ou tout autre serveur, ceci est uniquement pour SSR. Cela va router l'url /products/:id vers pages/product.js et fournir id dans le cadre de query dans getInitialProps :
server.get("/products/:slug", (req, res) => {
  return app.render(req, res, "/product", { slug: req.params.slug })
})
  1. Pour le routage côté client, vous utilisez next/link comme ceci :
<Link href="/product?slug=something" as="/products/something"> 

La raison pour laquelle vous devez fournir explicitement les href et as est que Next.js n'a connaissance d'aucune autre page côté client. Nous n'envoyons pas de manifeste de toutes les pages côté client et les routes suivantes sont chargées paresseux, ce qui est évolutif.

Il existe un package communautaire qui fournit des résumés en fournissant href et as en envoyant un manifeste prédéfini de toutes les routes, notez que nous vous recommandons de ne pas envoyer un manifeste complet de toutes les routes possibles car vous ne le faites pas. est plus évolutif

https://github.com/fridays/next-routes

Notez également que le rendu 404 n'est plus le comportement par défaut de Next.js. Au lieu de cela, nous rechargeons la page pour la fonctionnalité Zones.

Tous les 47 commentaires

Même problème +1

Comment rendez-vous le composant Link vers cette URL ? Utilisez-vous <Link href="/post/1"> ou <Link href="/post?id=1" as="/post/1"> ?

Actuellement, j'utilise <Link prefetch href={ /blog/${x.id} } /> . J'ai essayé <Link prefetch href={ /blog/${x.id} } as={ /blog/${x.id} } /> dans le passé et je viens de le rebrancher. Toujours le même problème.

Vos href et as props ne devraient pas être les mêmes, href est la vraie URL, si vous avez pages/blog.js et recevez l'identifiant comme requête alors href devrait être /blog?id=${x.id} et as est votre jolie URL personnalisée dans ce cas /blog/${x.id} .

@sergiodxa Je viens de mettre ce code en place.

<Link href={`/blog?id=${x.id}`} as={`blog/${x.id}`}>
    <a>Read Post</a>
 </Link>

Maintenant, il ré-affiche la page /blog à chaque clic tout en ajoutant le id à l'URL.

url error gif

@tgrecojs J'espère que cet extrait de code vous aidera

    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]}`

Rendurait comme https://www.someURL.com/journal/articlePath/morePath/evenMorePath

Je comprends comment fonctionne le chemin @ugiacoman ce n'est pas mon problème. Si vous pouvez voir dans mon rapport initial, je navigue avec succès vers chaque article de blog, mais le problème est cette étrange erreur 404 .

@tgrecojs J'ai fait un exemple de dépôt https://github.com/sergiodxa/next-custom-query (déployé : https://next-custom-query.now.sh/blog), vous pouvez voir comment utiliser le des URL personnalisées sans rechargement et une 404 utilisant le composant next/link comme décrit ci-dessus.

@sergiodxa J'apprécie ça ! Je viens de le vérifier et d'ajouter quelques appels asynchrones à l'API Google Blogger, ce que je fais actuellement ping. Ci-dessous, vous pouvez voir comment il se dirige vers l'itinéraire, mais il ne charge pas correctement les données.

Gif supprimé

Maintenant, ce problème est une reproduction légèrement différente de ce problème que ce qui est montré dans mon premier commentaire. Lorsque j'ai rencontré ce problème pour la première fois, je pensais que c'était parce que j'utilisais le redux et que l'état de l'application ne reportait pas les pages post/id . Cela m'a amené à intégrer un nouvel appel API pour chaque publication, tout comme je l'ai intégré dans l'application que vous avez créée, mais j'ai quand même constaté que j'avais le même problème.

J'avais des problèmes avec votre repo 😬 vous pouvez donc trouver mon code ici -> https://github.com/tgrecojs/next-custom-query-async . Faites-moi savoir que vous êtes pensées! ??

Il semble que vous obtenez un 400, lorsque vous bifurquez votre projet, j'obtiens la même erreur avec un message d'erreur useLimits. C'est probablement pourquoi vous obtenez cette erreur.

D'accord. J'étudierai un peu plus loin demain, mais je tiens à souligner que la vidéo que j'ai publiée lors de l'ouverture du problème ne fait pas de demande d'API sur la route /blog/:id . Au lieu de cela, il filtre les publications de mon magasin redux qui sont collectées lors de la transition de route /blog , ce qui ne peut donc pas être la raison pour laquelle je suis arrivé à ce problème. J'ai seulement implémenté le 2ème appel API (fait dans blog/:id ) car je pensais que cela avait quelque chose à voir avec mon redux-store mais je me suis retrouvé à recevoir la même erreur mais ce n'est pas l'implémentation actuelle dans mon code.

Dès que j'ai réalisé qu'il générait le même bogue, je suis revenu à un seul appel d'API (Inside /blog ), puis à filtrer le billet de blog nécessaire par identifiant.

@sergiodxa Je peux confirmer qu'il ne s'agit pas de limites d'utilisation. Vous verrez que le id n'est pas toujours correctement transmis à la route /blog/:id ... J'ai joint l'erreur 400 que je reçois. Vous verrez que id n'est pas défini et (dans ce cas) cela semble être la raison pour laquelle j'obtiens l'erreur.

J'ai inclus une autre vidéo ci-dessous. Avez-vous des idées sur la raison pour laquelle il peut se comporter de cette façon? Je n'ai pas modifié les balises <Link /> dans ce référentiel mais j'ai toujours le problème 😬 .

next-custom-query err

Encore une fois, je tiens à souligner que la vidéo ci-dessus montre ma reproduction de l'erreur à l'intérieur de l'exemple de référentiel que vous avez créé - https://github.com/sergiodxa/next-custom-query .

Je reçois également 404 clignotant sans aucune route personnalisée. Juste un fichier nommé orders.js dans pages/ avec ce code :

import { Component } from 'react';

class Orders extends Component {
  render() {
    return (
      <div>
        <h2>My Orders</h2>
      </div>
    )
  }
}

export default Orders;

Cela semble être un problème assez critique

J'ai essayé de le reproduire et c'est parce que la barre oblique à la fin de l'URL, si vous allez à /orders vous ne voyez pas le 404 mais si vous allez à /orders/ alors vous voyez ça 404 clignotant avant le contenu, cela se produit soit en mode dev soit en mode production.

Ah c'est un problème connu. https://github.com/zeit/next.js/issues/1189

Mon problème ne s'est pas posé en raison d'une barre oblique finale, il doit donc y avoir autre chose, n'est-ce pas ?

J'ai apporté quelques modifications à mon code et j'ai déployé 2 versions différentes, l'une utilisant prefetch et l'autre non. Je tiens à noter qu'aucune des deux applications n'est désormais capable de charger avec succès une route post/:id .

Avec Prefetch - https://tgrecojs-hltqztsjpx.now.sh/

On a remarqué que lorsque j'utilise prefetch dans le lien, il lance maintenant un Page Does Not Exist Error lors du rendu des liens pour chaque article de blog. Vous pouvez voir une capture d'écran de ma console ci-dessous.

screen shot 2017-08-26 at 1 06 25 pm

Sans Prefetch- https://tgrecojs-qzpspdjrin.now.sh/

Lorsque je n'utilise pas prefetch, l'erreur affichée ci-dessus n'existe plus mais elle ne rend pas l'application. Lorsque j'ai publié ce problème pour la première fois, mon composant initialisait mon blog pour chaque composant post/:id . Depuis, j'ai supprimé cela depuis que les messages individuels ne sont jamais rendus.

Faites-moi savoir si je peux fournir plus d'informations qui peuvent aider à diagnostiquer ce problème. ??

@tgrecojs J'ai presque exactement le même problème. prefetch n'a pas résolu mon problème.

Le comportement que j'obtiens est le suivant :

  • L'utilisateur clique sur le lien
  • Une erreur 404 s'affiche
  • La page se recharge (??)
  • Après rechargement, la bonne page s'affiche

J'espère que cela pourra aider à déboguer le problème !

Informations supplémentaires : Nœud v6.10.3 , Chrome Version 60.0.3112.90

EDIT : Déployez l'application pour que vous puissiez la tester https://datahub.now.sh/ , c'est le lien /@[username] qui a ce comportement

@Theo- le href dans ce lien suivant est user?id=1 , pouvez-vous essayer /user?id=1 place ? Je pense que le 404 est dû au fait que Next.js essaie d'atteindre /current/path/user?id=1 au lieu de /user?id=1 , mais lorsque la page se recharge, cela fonctionne bien à cause du rendu du serveur.

@sergiodxa qui l'a fait. Merci!

@tgrecojs J'ai eu le même comportement 404 clignotant. Dans mon cas, j'avais un lien avec une variable d'environnement qui ne fonctionnait pas sur le client, donc le 404 mais sur le serveur, cela fonctionnait. Résolu avec https://medium.com/the-tech-bench/next-js-environment-variables-d2f6ea1a1dca.

@andreaskeller hmmm ok je vais vérifier. merci ça!!! J'utilise actuellement UNIQUEMENT mes variables .env lorsque l'application est un rendu de serveur. J'ai un composant d'ordre supérieur qui utilise dotenv pour vérifier s'il s'agit de CSR ou de SSR, s'il s'agit de SSR, j'envoie alors la fonction nécessaire pour enregistrer les articles de blog.

ouais, j'ai déjà mes variables qui fonctionnent bien. Je rends ma route /blog utilisant un HOC qui obtient mon BLOGGER_API_KEY donc ça marche dans ces exemples... mes pages enfants de /post/:id n'en utilisent pas variables d'environnement.

je vais creuser un peu plus, j'espère que je pourrai aller au fond des choses !

Il semble que la plupart des problèmes ici soient résolus. Je vais également travailler sur ce problème https://github.com/zeit/next.js/issues/1189

Je ferme ça maintenant. Mais si nous devons faire quelque chose dans le noyau, faites-le moi savoir.

@sergiodxa selon notre conversation d'hier soir, j'ai créé la petite application barebones montrant mon problème. Faites-moi savoir si vous avez des questions à ce sujet! Je serais plus qu'heureux de vous renseigner sur tout ce qui s'y passe ! ??

Ce n'est pas réglé.

J'ai le même problème mais sans aucun itinéraire personnalisé. J'ai /pages/pipeline.tsx et /pipeline url fonctionne très bien tandis que /pipeline/ clignote 404, puis essaie de charger ma page sans appeler "getInitialProps" (puisque c'était 404 sur le serveur !).

@ex3ndr Je ne sais pas si cela
https://github.com/zeit/next.js#disabling -file-system-routing

Il y a de fortes chances que le prochain essaie de retirer le système de fichiers avant que votre itinéraire personnalisé ne soit atteint.

@moaxaca J'ai résolu de la même manière puisque j'avais besoin d'avoir mon propre routage personnalisé - je viens de désactiver complètement le suivant.

Je vois aussi ce problème. La solution de @moaxaca n'a pas fonctionné pour moi. Ce qui a été fait, c'est d'utiliser n'importe quel composant Link , mais d'opter à la place pour utiliser la méthode pushRoute next-routes.

Exemple de base :

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>
    )
  }

}

Cela semble comprendre et je ne vois pas l'erreur clignotante. Mais cela semble un peu rapide.

enregistrer le problème

J'ai déjà eu le même problème et j'ai pu le résoudre. J'utilise une configuration de serveur express. J'ai découvert que la raison pour laquelle la page 404 clignote avant de se charger sur la bonne page est que mon slug de page ne correspond pas au nom de mon composant.

Quand j'ai ce code le 404 clignote :

server.get('/search', (req, res) => {
    const actualPage = '/search_results'
    const queryParams = { filters: req.query }
    app.render(req, res, actualPage, queryParams)
  })

Notez que les valeurs /search et mes actualPage sont différentes.

Les clignotements 404 disparaissent lorsque je renomme mon composant et que les valeurs actualPage soient les mêmes que mon slug de page qui est search . Voir le code de travail ci-dessous :

server.get('/search', (req, res) => {
    const actualPage = '/search'
    const queryParams = { filters: req.query }
    app.render(req, res, actualPage, queryParams)
  })

Maintenant, les deux utilisent /search .

Désolé pour mes anglais.

il peut être judicieux de vérifier votre propriété next.config.js useFileSystemPublicRoutes . S'il est faux, cela signifie que vous devez définir vous-même tous les gestionnaires de routes dans server.js.

Cela corrige le 404 clignotant pour moi :

Relier

<Link href="/somepage?id=value" as="/somepage/value">

Du côté serveur

server.get("/somepage/:id", (req, res) => {
  return app.render(req, res, "/maps", { id: req.params.id })
})

Accéder aux paramètres sur la page

const { id } = this.props.url.query

Alors pour répondre à celui-ci une bonne fois pour toutes :

href => chemin à l'intérieur du répertoire pages + la chaîne de requête
as => rendu dans la barre d'URL du navigateur

Exemple:

Vous avez une URL appelée /products/:id

  1. Vous avez créé 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>
  }
}
  1. Vous ajoutez la route vers express ou tout autre serveur, ceci est uniquement pour SSR. Cela va router l'url /products/:id vers pages/product.js et fournir id dans le cadre de query dans getInitialProps :
server.get("/products/:slug", (req, res) => {
  return app.render(req, res, "/product", { slug: req.params.slug })
})
  1. Pour le routage côté client, vous utilisez next/link comme ceci :
<Link href="/product?slug=something" as="/products/something"> 

La raison pour laquelle vous devez fournir explicitement les href et as est que Next.js n'a connaissance d'aucune autre page côté client. Nous n'envoyons pas de manifeste de toutes les pages côté client et les routes suivantes sont chargées paresseux, ce qui est évolutif.

Il existe un package communautaire qui fournit des résumés en fournissant href et as en envoyant un manifeste prédéfini de toutes les routes, notez que nous vous recommandons de ne pas envoyer un manifeste complet de toutes les routes possibles car vous ne le faites pas. est plus évolutif

https://github.com/fridays/next-routes

Notez également que le rendu 404 n'est plus le comportement par défaut de Next.js. Au lieu de cela, nous rechargeons la page pour la fonctionnalité Zones.

Merci Tim, explication totalement claire!

@timneutkens
Si les href et as. Je passe la valeur différente. Comment puis-je obtenir la href et la valeur de as .
Je teste moi la démo. Je pense que req.params.slug sera la as . Alors comment pourrais-je obtenir la href .

@timneutkens Tu m'as sauvé je ne sais pas combien d'heures de recherche pénible pour mon problème :D

Comment rendez-vous le composant Link vers cette URL ? Utilisez-vous <Link href="/post/1"> ou <Link href="/post?id=1" as="/post/1"> ?

Tu devrais mettre ça dans la doc. :joie:

@sergiodxa

Alors pour répondre à celui-ci une bonne fois pour toutes :

href => chemin à l'intérieur du répertoire pages + la chaîne de requête
as => rendu dans la barre d'URL du navigateur

Exemple:

Vous avez une URL appelée /products/:id

  1. Vous avez créé 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>
  }
}
  1. Vous ajoutez la route à express ou à tout autre serveur, c'est _uniquement_ pour SSR. Cela va router l'url /products/:id vers pages/product.js et fournir id dans le cadre de query dans getInitialProps :
server.get("/products/:slug", (req, res) => {
  return app.render(req, res, "/product", { slug: req.params.slug })
})
  1. Pour le routage côté client, vous utilisez next/link comme ceci :
<Link href="/product?slug=something" as="/products/something"> 

La raison pour laquelle vous devez fournir explicitement les href et as est que Next.js n'a connaissance d'aucune autre page côté client. Nous n'envoyons pas de manifeste de toutes les pages côté client et les routes suivantes sont chargées paresseux, ce qui est évolutif.

Il existe un package communautaire qui fournit des résumés en fournissant href et as en envoyant un manifeste prédéfini de toutes les routes, notez que nous vous recommandons de ne pas envoyer un manifeste complet de toutes les routes possibles car vous ne le faites pas. est plus évolutif

https://github.com/fridays/next-routes

Notez également que le rendu 404 n'est plus le comportement par défaut de Next.js. Au lieu de cela, nous rechargeons la page pour la fonctionnalité Zones.

ce que je peux faire si je n'ai qu'un tableau d'en-tête de liste comme :
[ home: '/home', about:'/about', post: 'post/:post_id?' ] .
Dans la suite, je n'obtiens qu'une as's , mais qu'en est-il de href ? Merci: D

Et si vous utilisez router.push() au lieu de <Link> comment pouvez-vous obtenir les mêmes résultats ?

@justinmchase Je viens d'avoir le même problème. Consultez la documentation du prochain routeur si vous ne l'avez pas déjà fait.

Vous pouvez l'utiliser comme Router.push(url, as, options) :

Router.push('/post/[pid]', '/post/abc')

@timneutkens J'aimerais héberger mon application next.js sur ZEIT.now mais cela n'a pas la possibilité d'exécuter un serveur express. Est-ce que je perds mes jolies URL maintenant et ne peux faire que param=value&param=value ou existe-t-il un autre moyen ? L' exemple que Sergio a posté ne semble pas prometteur

J'ai essayé des routes dynamiques mais maintenant mon application à page unique est cassée et des liens tels que :

<Link href={`/integration?slug=${slug}`} as={`/integration/${slug}`}>

provoquent maintenant un rechargement complet de la page car http://localhost :8080/_next/static/development/pages/integration.js renvoie un 404 introuvable.

@timneutkens J'aimerais héberger mon application next.js sur ZEIT.now mais cela n'a pas la possibilité d'exécuter un serveur express. Est-ce que je perds mes jolies URL maintenant et ne peux faire que param=value&param=value ou existe-t-il un autre moyen ? L' exemple que Sergio a posté ne semble pas prometteur

Vous n'avez pas besoin d'un serveur personnalisé pour les routes dynamiques, voir https://nextjs.org/docs/routing/dynamic-routes

@timneutkens Merci pour votre réponse rapide, j'ai essayé des routes dynamiques mais je vais casser l'application d'une seule page (voir mise à jour). Exécution locale avec next dans mon script package.json en mode dev.

Résolu en ayant un pages/integration/index.js avec le code et un pages/integration/[slug].js avec :

import ProductDetailPage from './index'
export default ProductDetailPage

La bonne façon de faire ce que vous avez décrit est de créer pages/integration/[slug].js

Et liez-le de cette façon:

<Link href={`/integration/[slug]`} as={`/integration/${slug}`}>

Salut, puis-je demander pourquoi quand j'appelle celui-ci

Router.push( '/about?id=1234','/about')

l'identifiant ne peut pas être récupéré, et la page que j'utilise est [...index].js qui est une page multi-dynamique, mais si je dirige vers une autre page qui n'est pas dynamique, cela peut fonctionner correctement, exemple car.js pousser vers véhicule.js..
Existe-t-il un meilleur moyen de pousser vers ma page de capture dynamique, puis de masquer l'identifiant et de toujours pouvoir le récupérer ..?

Cette page vous a été utile?
0 / 5 - 0 notes