在盖茨比以编程方式限制路线

时间:2018-05-25 15:18:42

标签: reactjs react-router gatsby

在Gatsby中,我如何以编程方式限制路线?使用react-router,我发现可以使用<Redirect>进行<Route>,但如何在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 />)。这将是一个糟糕的用户体验,因为他们必须从头开始重新输入所有信息,而且我无法为无效输入添加样式等等。我想知道是否有更好的方法用盖茨比来做这件事。

或者,我是否必须从头开始构建表单功能(即更直接地使用Redux,Router等),而不是依赖于Gatsby的更高抽象级别?

1 个答案:

答案 0 :(得分:5)

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)在您想要的前缀“仅客户端”路径

中定义路由

假设您要限制访问您网站的 / 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>
);
  

这些路由仅存在于客户端上,与应用程序构建的资产中的index.html文件不对应。如果您希望人们直接访问客户端路由,则需要设置服务器以正确处理这些路由。 (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)
  }
}