在 Gatsby 中以编程方式限制路由
Restrict routes programmatically in Gatsby
在 Gatsby 中,我将如何以编程方式限制路由?使用 react-router,我发现可以用 <Route>
做一个 <Redirect>
,但这在 Gatsby 中如何实现?做这样的事情...
<Route exact path="/" render={() => (
loggedIn ? (
<Redirect to="/dashboard"/>
) : (
<PublicHomePage/>
)
)}/>
我应该把这个文件放在 Gatsby 的什么地方?我会把它放在 src/pages
还是其他地方?
已编辑,要求进一步说明...
根据@Nenu 和 Gatsby 文档的建议,我能够完成这项工作。文档给出了一个非异步示例,所以我不得不调整它以便与这样的远程服务器交互...
async handleSubmit(event) {
event.preventDefault()
await handleLogin(this.state)
.then(response => _this.setState({isLoggedIn: isLoggedIn()}))
.catch(err => { console.log(err) });
}
另外,我可以用 <PrivateRoute />
来处理这个。
不幸的是,当我渲染时使用...
render() {
if (isLoggedIn()) {
return <Redirect to={{ pathname: `/app/profile` }} />
}
return (
<View title="Log In">
<Form
handleUpdate={e => this.handleUpdate(e)}
handleSubmit={e => this.handleSubmit(e)}
/>
</View>
)
}
...虽然我确实这样做 <Redirect to={{ pathname:
/app/profile}} />
,但我注意到在我重定向之前的一瞬间,表单字段被清空,只有在那之后我才被重定向到 /app/profile
(来自 /app/login
)。此外,如果我输入的密码不正确,我的整个表单都会重新呈现(再次重新呈现 <View />
)。这将是一个糟糕的用户体验,因为他们必须从头开始重新输入所有信息,而且我无法为无效输入添加样式等。我想知道是否有更好的方法用 Gatsby 做到这一点。
或者,我是否必须更多地从头开始构建表单功能(即,更直接地使用 Redux、Router 等)而不是依赖于 Gatsby 的更高抽象级别?
Gatsby 在后台使用 react-router,因此您可以使用它定义您的客户端专用路由。
与 gatsby 一样,github 存储库中有一个非常好的示例:
https://github.com/gatsbyjs/gatsby/tree/master/examples/simple-auth
关于它的文档:
https://www.gatsbyjs.org/docs/building-apps-with-gatsby/#client-only-routes--user-authentication
综上所述,就是这样做的:
1) 在/src/components
中创建一个PrivateRoute
组件
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={props =>
!isLoggedIn() ? (
// If we’re not logged in, redirect to the login page.
<Redirect to={{ pathname: `/app/login` }} />
) : (
<Component {...props} />
)
}
/>
);
2) 在你想要的前缀 "client-only" path
中定义路由
假设您想限制对您网站的 /app/:path 部分的访问,然后在 /src/pages/app.js:
const App = () => (
<div>
<PrivateRoute path="/app/profile" component={Home} />
<PrivateRoute path="/app/details" component={Details} />
<Route path="/app/login" component={Login} />
</div>
);
These routes will exist on the client only and will not correspond to index.html files in an app’s built assets. If you wish people to visit client routes directly, you’ll need to setup your server to handle these correctly. (source)
3) 在 gatsby-node.js
中将客户端路由列入白名单
exports.onCreatePage = async ({ page, boundActionCreators }) => {
const { createPage } = boundActionCreators
// page.matchPath is a special key that's used for matching pages
// only on the client.
if (page.path.match(/^\/app/)) {
page.matchPath = `/app/:path`
// Update the page.
createPage(page)
}
}
在 Gatsby 中,我将如何以编程方式限制路由?使用 react-router,我发现可以用 <Route>
做一个 <Redirect>
,但这在 Gatsby 中如何实现?做这样的事情...
<Route exact path="/" render={() => (
loggedIn ? (
<Redirect to="/dashboard"/>
) : (
<PublicHomePage/>
)
)}/>
我应该把这个文件放在 Gatsby 的什么地方?我会把它放在 src/pages
还是其他地方?
已编辑,要求进一步说明...
根据@Nenu 和 Gatsby 文档的建议,我能够完成这项工作。文档给出了一个非异步示例,所以我不得不调整它以便与这样的远程服务器交互...
async handleSubmit(event) {
event.preventDefault()
await handleLogin(this.state)
.then(response => _this.setState({isLoggedIn: isLoggedIn()}))
.catch(err => { console.log(err) });
}
另外,我可以用 <PrivateRoute />
来处理这个。
不幸的是,当我渲染时使用...
render() {
if (isLoggedIn()) {
return <Redirect to={{ pathname: `/app/profile` }} />
}
return (
<View title="Log In">
<Form
handleUpdate={e => this.handleUpdate(e)}
handleSubmit={e => this.handleSubmit(e)}
/>
</View>
)
}
...虽然我确实这样做 <Redirect to={{ pathname:
/app/profile}} />
,但我注意到在我重定向之前的一瞬间,表单字段被清空,只有在那之后我才被重定向到 /app/profile
(来自 /app/login
)。此外,如果我输入的密码不正确,我的整个表单都会重新呈现(再次重新呈现 <View />
)。这将是一个糟糕的用户体验,因为他们必须从头开始重新输入所有信息,而且我无法为无效输入添加样式等。我想知道是否有更好的方法用 Gatsby 做到这一点。
或者,我是否必须更多地从头开始构建表单功能(即,更直接地使用 Redux、Router 等)而不是依赖于 Gatsby 的更高抽象级别?
Gatsby 在后台使用 react-router,因此您可以使用它定义您的客户端专用路由。
与 gatsby 一样,github 存储库中有一个非常好的示例:
https://github.com/gatsbyjs/gatsby/tree/master/examples/simple-auth
关于它的文档:
https://www.gatsbyjs.org/docs/building-apps-with-gatsby/#client-only-routes--user-authentication
综上所述,就是这样做的:
1) 在/src/components
中创建一个PrivateRoute
组件
const PrivateRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={props =>
!isLoggedIn() ? (
// If we’re not logged in, redirect to the login page.
<Redirect to={{ pathname: `/app/login` }} />
) : (
<Component {...props} />
)
}
/>
);
2) 在你想要的前缀 "client-only" path
中定义路由假设您想限制对您网站的 /app/:path 部分的访问,然后在 /src/pages/app.js:
const App = () => (
<div>
<PrivateRoute path="/app/profile" component={Home} />
<PrivateRoute path="/app/details" component={Details} />
<Route path="/app/login" component={Login} />
</div>
);
These routes will exist on the client only and will not correspond to index.html files in an app’s built assets. If you wish people to visit client routes directly, you’ll need to setup your server to handle these correctly. (source)
3) 在 gatsby-node.js
中将客户端路由列入白名单exports.onCreatePage = async ({ page, boundActionCreators }) => {
const { createPage } = boundActionCreators
// page.matchPath is a special key that's used for matching pages
// only on the client.
if (page.path.match(/^\/app/)) {
page.matchPath = `/app/:path`
// Update the page.
createPage(page)
}
}