Next.js页面在刷新时出现404错误

12

我正在使用Next.js和GraphQL进行Shopify POC。

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

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

“handle”是集合的名称,因此在浏览器中的URL看起来像http://localhost:3000/new-releases/product/Plattan-2-Bluetooth,但实际上它只是使用名为“products”的页面,并传递产品ID。

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

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

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;
2个回答

21

您可以在名为next.config.js的文件中尝试这些内容,该文件位于您项目的根目录下。

module.exports = {
  trailingSlash: true
}

请查看此链接


这个对我解决了问题,谢谢。我从来没想到它会这么简单! - jesseSpencer
4
注意:exportTrailingSlash已更名为trailingSlash - jesseSpencer
谢谢,我也遇到了这个问题。在我的情况下,当刷新页面时,页面会被重定向到主页,而地址栏仍保留着页面的URL。我正在使用 router.reload(window.location.pathname) - Deep Kakkar
可以了。在尝试了除了这个答案以外的所有方法,比如getStaticProps/Paths、在github上寻找解决方案、强制生产等等之后,这就是我需要的。在手动在URL上添加斜杠后,我忽略了这个答案。 - Lalit Fauzdar
根值具有意外属性exportTrailingSlash,不属于允许的属性列表(amp、analyticsId、assetPrefix、basePath、cleanDistDir、compiler、compress、crossOrigin等)。 - Peter Palmer
显示剩余4条评论

7
这是因为当您使用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存储库中有许多示例,其中包括一个使用Express的示例。这也在他们网站的“学习”部分中涵盖在一个名为服务器端支持干净URL的教程的教程中。
如果您决定使用Express,您最终会得到类似以下内容的东西:
server.get('/:collection/product/:productUrl', (req, res) => {
  return app.render(req, res, '/product', { productUrl: req.params.productUrl})
})

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

谢谢。我有一个运行“graphql-yoga”的后端服务器,我应该将其添加到其中还是这是专门为nextjs的单独后端? - Adam
这是Next.js的独立后端。 - Matthew Rapati
那么,使用这个 server.js 的构建过程是什么? - Md Abdul Halim Rafi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接