尝试在 GatsbyJS 中实现仅客户端路由时出现运行时错误
Runtime error when trying to implement client-only routes in GatsbyJS
我正在尝试遵循 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
也渲染成功了,但是当我点击其中一个时,出现运行时错误:
未处理的运行时错误
在您的文件中发现一个未处理的运行时错误。请参阅下面的列表来修复它:
eval 函数错误 ./node_modules/@gatsbyjs/reach-router/es/index.js:698
无法读取未定义的 属性 'path'
./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;
所有其他文件保持不变。但是,单击 link.
后错误仍然存在于 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
后,页面可以再次加载。此时单击主页 Link 不会触发任何错误。
似乎正在发生的事情是您的路径没有被 Gatsby 找到。我认为您只需要将 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
).
我正在尝试遵循 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
也渲染成功了,但是当我点击其中一个时,出现运行时错误:
未处理的运行时错误
在您的文件中发现一个未处理的运行时错误。请参阅下面的列表来修复它:
eval 函数错误 ./node_modules/@gatsbyjs/reach-router/es/index.js:698
无法读取未定义的 属性 'path'
./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;
所有其他文件保持不变。但是,单击 link.
后错误仍然存在于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
后,页面可以再次加载。此时单击主页 Link 不会触发任何错误。
似乎正在发生的事情是您的路径没有被 Gatsby 找到。我认为您只需要将 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
).