这是使用钩子在React中保护路由的正确方法吗?

时间:2019-08-28 09:22:29

标签: reactjs react-router

我在网上找到的所有解决方案似乎都很复杂,所以我写了这种简单的保护路线的方法,这也是正确的方法吗?

 <Route
    exact
    path="/Cart"
    component={() =>
    this.props.loading === true ? (
          <Cart />
   ) : (
          <Redirect to="/login" />
        )
   }
  />

这种方法有什么弊端吗?

4 个答案:

答案 0 :(得分:3)

尽管您的方法可能有效,但它被认为是一个非常糟糕的设计。因此,您可能需要考虑以下一些可能的问题和注意事项:

  1. 道具可以出于各种原因传递给孩子,其中很多与有效请求无关,因此即使您不希望渲染购物车,您的函数也可能返回true。不要对道具进行安全保护。不仅如此,如果您将来不得不更改这些道具,例如使用观察者或更高阶的组件设计,还必须重做所有事情。另外,如果要在此服务器端进行渲染,则将增加额外的服务器负载,因为您的整个组件都在渲染之前甚至尚未验证对它的请求。

  2. 您必须对编写的每个组件执行此操作,这意味着随着时间的推移,您的项目将无法维护。更好的方法是让您的组件订阅一个钩子或回调函数并导出该函数,以便您甚至在呈现该组件之前就可以对其进行检查和验证。您可以将组件本身及其验证功能导出为2个单独的导出。

  3. 在网络通信中,特别是在安全性方面,标准方法是创建一个集中式API并通过它来验证所有请求,以便您的代码可维护,并且以便将来将来需要更改该代理时您可以轻松地做到这一点。具体来说,在React中,您有两个选择之一,每个选择都有其优点和缺点,一些选择创建一个集中式API,并通过所有组件进行路由,其他选择对每个组件进行路由,以实现每个组件的更多调制和自治。

  4. 如果您这样做是为了说40个组件,那么您的客户会说,哦,实际上,我们的业务逻辑发生了变化,并且我们需要此规则,因此您将不得不改变这一点,每个组件。而是创建诸如回调或集中式代理之类的东西,并通过它路由所有安全性和验证。

始终记住,在开发中,长期可维护性和可伸缩性应始终是您的主要考虑因素。

答案 1 :(得分:2)

所有内容都适用于您的示例,但是实际上您无法将逻辑重用于其他私有组件/路由,因此最好对所有经过身份验证的路由进行某种包装。

这应该是PrivateRoute

的简单示例
function PrivateRoute({ component: Component, isAuthenticated, ...rest }) {
    return (
        <Route
            {...rest}
            render={props =>
                isAuthenticated() ? <Component {...props} /> : <Redirect to="/login" />
            }
        />
    );
}

用法

<PrivateRoute
    exact
    path="/Cart"
    component={Cart}
    isAuthenticate={() => checkAuth()} // or whatever method you use for checking auth
/>

当然,如果您使用Redux,进行异步身份验证检查或其他复杂的逻辑,则可以很好地改善这一点,但这应该为您提供一个良好的开端。

答案 2 :(得分:2)

您不能在您的情况下重用代码,但这是您可以遵循的简单解决方案。 称为HOC,高阶组件。这意味着您必须创建一个新组件,其中包含要保护的组件

示例:<Auth path="/login" component={Another} />

此处Auth是用于保护需要保护的组件的组件

Auth组件应如下所示:

function Auth({ component: Component, ...rest }) {
  const counter = useSelector(state => state);
  return (
    <Route
      {...rest}
      render={props =>
        counter ? <Component {...props} /> : <Redirect to="/sign" />
      }
    />
  );
}
export default Auth

答案 3 :(得分:1)

您的代码可以使用,但是您应该使用其他组件来保护路线

const PrivateRoute = ({ Component, ...rest }) => (
    <Route {...rest} render={props => isAuthenticated() ? (
        <Component {...props} />
    ) : (
            <Redirect to={
                {
                    pathname: '/login',
                    state: {
                        form: props.location
                    }
                }} />
    )} />
)

然后在路由器文件中导入PrivateRoute并使用

 <PrivateRoute exact path='/Cart' component={EditPost} />