【问题标题】:Runtime error when trying to implement client-only routes in GatsbyJS尝试在 GatsbyJS 中实现仅限客户端的路由时出现运行时错误
【发布时间】:2021-08-14 08:20:57
【问题描述】:

我正在尝试遵循 Gatsby 网站上的基本示例。到目前为止,这些是我的代码:

// pages/app.js
import { Router } from '@reach/router';
import { Link } from 'gatsby';
import * as React from 'react';

import Browse from '../components/Browse';
import Upload from '../components/Upload';

const AppPage = () => (
  <>
    <nav>
      <Link to "/app/browse">Browse Link</Link>
      <Link to "/app/upload">Upload Link</Link>
    </nav>
    <main>
      <Router basepath="/app">
        <Browse path="/browse">Browse</Browse>
        <Upload path="/upload">Upload</Upload>
      </Router>
    </main>
  </>
);

export default AppPage;

// components/Browse.tsx
import * as React from 'react';

import { RouteComponentProps } from '@reach/router';

type BrowseProps = {
  children?: string,
} & RouteComponentProps;

const Browse = ({ children }: BrowseProps) => <div>{children}</div>;

Browse.defaultProps = {
  children: '',
};

export default Browse;

// components/Upload.tsx
// Identical to Browse.tsx, except it's named Upload
type UploadProps {...}

const Upload = ...;

export default Upload;

为了帮助配置仅限客户端的路径,我使用gatsby-plugin-create-client-paths 来帮助按照网站上的建议自动执行该过程。它已被添加到gatsby-config.js,如下所示:

// gatsby-config.js
plugins: [
  "gatsby-plugin-react-helmet",
  {
    resolve: "gatsby-plugin-create-client-paths",
    options: {
      prefixes: ["/app/*"],
    },
  },
  {
    resolve: "gatsby-plugin-manifest",
    options: {
      icon: "src/images/icon.png",
    },
  },
]

据我所知,这应该就是让它工作所需的全部内容。于是我启动了开发服务器:

npm run develop

我成功打开了http://localhost:8000/app/,两个Links都成功渲染了,但是当我点击其中一个时,出现了运行时错误:

未处理的运行时错误

在您的文件中发现一个未处理的运行时错误。请参阅下面的列表进行修复:

./node_modules/@gatsbyjs/reach-router/es/index.js:698

中的函数eval出错

无法读取未定义的属性“路径”

./node_modules/@gatsbyjs/reach-router/es/index.js:698
 696 |       return React.Children.map(element.props.children, createRoute(basepath));
  697 |     }
> 698 |     !(element.props.path || element.props.default || element.type === Redirect) ? process.env.NODE_ENV !== "production" ? invariant(false, "<Router>: Children of <Router> must have a `path` or `default` prop, or be a `<Redirect>`. None found on element type `" + element.type + "`") : invariant(false) : void 0;
  699 |
  700 |     !!(element.type === Redirect && (!element.props.from || !element.props.to)) ? process.env.NODE_ENV !== "production" ? invariant(false, "<Redirect from=\"" + element.props.from + "\" to=\"" + element.props.to + "\"/> requires both \"from\" and \"to\" props when inside a <Router>.") : invariant(false) : void 0;
  701 |

这是什么意思?我错过了什么吗?是不是因为我使用的是开发环境而不是生产环境导致失败?

更新:根据Ferran的回答,我修改了我的代码如下,将pages/index.js重构为pages/app/[...].js

// pages/app/[...].js
import { Router } from '@reach/router';
import { Link } from 'gatsby';
import * as React from 'react';

import Browse from '../../components/Browse';
import Upload from '../../components/Upload';

const AppPage = () => (
  <>
    <nav>
      <Link to "/app/browse">Browse Link</Link>
      <Link to "/app/upload">Upload Link</Link>
    </nav>
    <main>
      <Router basepath="/app">
        <Browse path="/browse">Browse</Browse>
        <Upload path="/upload">Upload</Upload>
      </Router>
    </main>
  </>
);

export default AppPage;

所有其他文件保持不变。但是,单击链接后,错误仍然存​​在于http://localhost:8000/app/

更新:尝试添加Home 路由:

// pages/app/[...].js
import { Router } from '@reach/router';
import { Link } from 'gatsby';
import * as React from 'react';

import Browse from '../../components/Browse';
import Home from '../../components/Home';
import Upload from '../../components/Upload';

const AppPage = () => (
  <>
    <nav>
      <Link to "/app/">Home Link</Link>
      <Link to "/app/browse">Browse Link</Link>
      <Link to "/app/upload">Upload Link</Link>
    </nav>
    <main>
      <Router basepath="/app">
        <Browse path="/browse">Browse</Browse>
        <Upload path="/upload">Upload</Upload>
        <Browse path="/">Home</Browse>
      </Router>
    </main>
  </>
);

export default AppPage;

添加后,http://localhost:8000/app/ 立即触发了相同的错误。删除Home 路由而不是Link 后,页面可以再次加载。此时点击主页链接不会触发任何错误。

【问题讨论】:

    标签: javascript reactjs typescript routes gatsby


    【解决方案1】:

    似乎正在发生的事情是盖茨比找不到您的路径。我认为您只需将app.js 移动到src/pages/app/[...].js 中(将文件重命名为[...].js)。

    您可以在他们的GitHub 中关注 Gatsby 的官方示例。盖茨比文档中的代码建议:

    // src/pages/app/[...].js
    
    import React from "react"
    import { Router } from "@reach/router"
    import Layout from "../components/Layout"
    import Profile from "../components/Profile"
    import Details from "../components/Details"
    import Login from "../components/Login"
    import Default from "../components/Default"
    import PrivateRoute from "../components/PrivateRoute"
    
    const App = () => {
      return (
        <Layout>
          <Router basepath="/app">
            <PrivateRoute path="/profile" component={Profile} />
            <PrivateRoute path="/details" component={Details} />
            <Login path="/login" />
            <Default path="/" />
          </Router>
        </Layout>
      )
    }
    export default App
    

    [...].js 表示法使用File System Route API,它在/app 之后标记URL 的任何动态段(由于文件夹结构,app/[...].js)。

    【讨论】:

    • 见我上面的更新。我尝试按照您的建议更新代码,但错误仍然存​​在。
    • 假设您修复了 Link 结构。您能否确认您不能直接使用/browse/app/browse 等进行导航?
    • 是的,Link 代码与上面我的问题中显示的相同。不,直接访问端点是行不通的。同样的错误。
    • 尝试删除children 并保留&lt;Upload path="/upload"/&gt; 之类的组件(自动关闭)。由于它不是一个链接,它只是呈现更好的匹配 window.location
    • 现在可以使用了!多么奇怪,您似乎无法将路由视为具有内部文本或其他嵌套内容的普通组件。
    猜你喜欢
    • 2019-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-23
    • 2022-07-10
    • 1970-01-01
    • 1970-01-01
    • 2021-06-09
    相关资源
    最近更新 更多