Nextjs 页面在刷新时转到 404 [英] Nextjs page goes to 404 on refresh

查看:88
本文介绍了Nextjs 页面在刷新时转到 404的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将 nextjs 和 graphql 用于 shopify POC.

我有一个组件显示产品列表,其中包含指向产品页面的链接

<链接as={`${handle}/product/${url}`}href={`/product?id=${item.id};`}><a>{item.title}</a></链接>

handle 是集合名称,所以浏览器中的 url 看起来像http://localhost:3000/new-releases/product/Plattan-2-蓝牙,但在幕后,它实际上只是使用一个名为产品的页面,我正在传递产品 ID.

现在在 product.js(粘贴在下面)中,我正在获取 id 的查询字符串值并执行另一个查询以获取产品.一切正常,但是如果我点击刷新或复制并将网址粘贴到新窗口中,我会得到 404.

我知道这与路由有关,但我不确定我需要做什么来解决这个问题.谢谢

import React, { Component } from 'react';从 'prop-types' 导入 PropTypes;从'react-apollo'导入{查询};从'graphql-tag'导入gql;类产品扩展组件{静态异步 getInitialProps({query}) {console.log("查询", 查询)返回查询 ?{ id: query.id.replace(';', '') } : {}}使成为() {const PRODUCT_FRAGMENT = gql`片段 ProductPage 在 Product {标题描述描述HTMLID图像(第一个:10,最大宽度:600){边{节点{ID替代文本原始源}}}}`;const PRODUCT_FETCH_QUERY = gql`查询 PRODUCT_FETCH_QUERY {节点(ID:${this.props.id}"){__类型名...产品页面}}${PRODUCT_FRAGMENT}`;返回 (<div><查询查询={PRODUCT_FETCH_QUERY}>{({ 数据,错误,加载}) =>{console.log("数据", 数据)if (loading) return <p>Loading...</p>if (error) return <p>Error: {error.message}</p>返回空}}</查询>

);}}product.propTypes = {};出口默认产品;

解决方案

这是因为当您使用 next/link 组件时,href 道具具有真实"带有商品 ID 集的查询参数的页面的 URL.这意味着在客户端(浏览器)上,Next.js 可以加载带有数据查询参数的正确页面(您的 product.js 页面).

但是当您从服务器加载时,无论是通过重新加载页面还是在新窗口中打开它,Next.js 都不知道要加载哪个页面,在这种情况下,我认为它会尝试找到文件 ./pages/new-releases/product/Plattan-2-Bluetooth.js,当然不存在.

如果你想拥有这些类型的 URL,你必须确保请求也被路由到服务器上正确的页面文件 (./pages/product.js).您可以通过创建自定义服务器来完成此操作.Next.js 存储库中有一堆 examples,其中包括一个使用Express.这也包含在该网站的学习"部分的名为 服务器端对干净 URL 的支持

如果您决定使用 Express,您最终会得到如下结果:

server.get('/:collection/product/:productUrl', (req, res) => {返回 app.render(req, res, '/product', { productUrl: req.params.productUrl})})

这将呈现产品页面,并且您将在 getInitialProps() 中的 query 对象上提供 productUrl.当然,现在您需要使用它而不是产品 ID 来获取数据.

I'm using nextjs and graphql for a shopify POC.

I have a component that shows a list of products with links on them that point to the product page

<Link
   as={`${handle}/product/${url}`}
   href={`/product?id=${item.id};`}>
   <a>{item.title}</a>
</Link>

handle is the collection name so the url in the browser will look like http://localhost:3000/new-releases/product/Plattan-2-Bluetooth but behind the scenes its really just using a page called products and i'm passing the product id.

Now in product.js (pasted below) i'm getting the query string value of the id and doing another query to get the product. All works fine but then if i hit refresh or copy and paste the url into a new window i get 404.

I know this is something to do with routing but i'm not sure what i need to do to fix this. Thanks

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Query } from 'react-apollo';
import gql from 'graphql-tag';


class product extends Component {
  static async getInitialProps({query}) {
    console.log("query", query)
    return query ? { id: query.id.replace(';', '') } : {}
  }

  render() {

    const PRODUCT_FRAGMENT = gql`
        fragment ProductPage on Product {
          title
          description
          descriptionHtml
          id
          images(first: 10, maxWidth: 600) {
            edges {
              node {
                id
                altText
                originalSrc
              }
            }
          }
        }
      `;

    const PRODUCT_FETCH_QUERY = gql`
      query PRODUCT_FETCH_QUERY {
        node(id: "${this.props.id}") {
          __typename
          ...ProductPage
        } 
      }
      ${PRODUCT_FRAGMENT}
    `;

    return (
      <div>
         <Query query={PRODUCT_FETCH_QUERY}>
              {({ data, error, loading }) => {
                console.log("data", data)
                if (loading) return <p>Loading...</p>
                if (error) return <p>Error: {error.message}</p>
                return null}
              }
            </Query>
      </div>
    );
  }
}

product.propTypes = {

};

export default product;

解决方案

This is because when you use the next/link component the href prop has the "real" URL to the page with the query parameter for the item ID set. This means that on the client (the browser), Next.js can load the right page (your product.js page) with the parameter for your data query.

But when you load from the server, either by reloading the page or opening it in a new window, Next.js doesn't know what page to load and in this case I think it will try to find the file ./pages/new-releases/product/Plattan-2-Bluetooth.js, which of course doesn't exist.

If you want to have these kinds of URLs you have to make sure the request gets routed to the right page file (./pages/product.js) on the server as well. You can do this by by creating a custom server. There are a bunch of examples in the Next.js repo including one using Express. This is also covered in the "Learn" section of there website in a tutorial called Server Side Support for Clean URLs

If you decide to use Express, you will end up with something like:

server.get('/:collection/product/:productUrl', (req, res) => {
  return app.render(req, res, '/product', { productUrl: req.params.productUrl})
})

This will render the product page, and you'll have productUrl available on the query object in getInitialProps(). Of course now you will need to fetch your data with that instead of the product id.

这篇关于Nextjs 页面在刷新时转到 404的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆