react-router6对比vue实现私密路由保护功能+重定向之前页面

简介:在vue中,实现路由保护有router.beforeEach的全局路由守卫,afterEach后置路由首位和beforeEnter独享路由守卫,那么在react中该怎么实现?
基于react的灵活性,实现以上方式的方法基本我分为3种,组件校验,函数校验,或者两者结合。对于利用js函数形式校验并管理路由可以看这篇文章,详细介绍了usRoutes()统一管理路由和校验的方式。这里只大致介绍组件形式。

思路:首先实现私密路由保护,react中除了函数形式外,组件形式是使用一个私密路由组件来包裹需要保护的组件,这时候就需要用到token,或者别的什么请求值。所以首先让这些值得能够在全局中传递,然后在私密组件中进行判断校验。 至于重定向之前页面或者跳转其他页面就只需要用到react-router6的hook和组件就ok

配置路由

注:此处只是简单的demo,真实项目里面路由是统一管理,用useRoutes这个hooks拿取,搭配<Outlet/>或者直接map遍历的形式,像以下的用在少部分处

const App = () => {
/......./
  return (
    <>
      <h1>React Router</h1>
      <Routes>
        <Route index element={<A />} />
        <Route path="/home" element={<A />} />
        <Route path="/bpath" element={<B />} />
        <Route path="*" element={<Error />} />
      </Routes>
    </>
  );
};

实现一个Context管理需要的状态组件,包裹路由

组件

// AuthProvider.jsx

//context
export const demoTwoContext = React.createContext()
//组件封装
const AuthProvider = (props) => {
  const [token, setToken] = useState(null);
  
  const handleLogin = useCallback(async() => {
    const token = await 请求数据(用到redux或者mobx);
    setToken(token);
  }, []);

  const handleLogout = useCallback(() => {
    setToken(null);
  }, []);
  
//添加其他方法或者状态

  const value = {
    token,
    onLogin: handleLogin,
    onLogout: handleLogout,
  };

  return <demoTwoContext.Provider value={value}>
  {props.children}
  </demoTwoContext.Provider>;
};

export default AuthProvider;

可以把value里面的值都封装到一个hook里面,方便拿取

//useAuth.js
import React from "react";
import { demoTwoContext } from "./AuthProvider ";

export const useAuth = () => {
  return React.useContext(demoTwoContext);
};

包裹后的App组件

const App = () => {
/......./
  return (
  -  <>
  +  <AuthProvider>
      <h1>React Router</h1>
      <Routes>
        <Route index element={<A />} />
        <Route path="/home" element={<A />} />
        <Route path="/bpath" element={<B />} />
        <Route path="*" element={<Error />} />
      </Routes>
  -  </>
  +  </AuthProvider>
  );
};

私密路由保护:没登陆,没token值,B组件就进不去

即使知道B组件的路由地址,想直接输入url进入,这个方式也可以阻止。

因为要用它包裹其他组件,所以返回一个children
PrivateRoute.jsx

import React from "react";
import { Navigate } from "react-router-dom";//react router6的跳转组件
import { useAuth } from "./hooks/useAuth";
/**
 *组件将检查身份验证令牌是否存在。
 *如果存在,则该组件将呈现其子级。
 *如果它不存在,用户将获得一个条件重定向
 */
const ProtectedRoute = (props) => {
  const { token } = useAuth(); //刚才封装的hook,这样就不用一直useContext拿值了

  if (!token) {
    return <Navigate to="/home" replace />;
  }
  return props.children
};

export default ProtectedRoute;

包裹B组件,实现如下功能

此时实现功能:进去B组件时候没有登陆,无token值,就进不去,会重定向/home页面,同时知道B组件url地址,直接输入也会被拦截

 <Routes>
    <Route index element={<A />} />
    <Route path="/home" element={<A />} />
    <Route
       path="/dashboard"
       element={//现在,当用户单击按钮注销时,他们将通过新的受保护路由获得隐式重定向,因为令牌不再存在。此外,如果用户未通过身份验证,则此用户无法访问受保护的路由
            <ProtectedRoute>
              <B />
            </ProtectedRoute>
          }
        />
        <Route path="*" element={<Error />} />
      </Routes>

重定向之前页面

登录后,您将被重定向到以前访问过的页面。换句话说:如果您在受保护的路由上打开应用程序,但您没有登录,则会重定向到“登录”页面。登录后,您将获得重定向到所需的受保护路由。

const ProtectedRoute = (props) => {
  const { token } = useAuth();
  const location = useLocation();

  if (!token) { //重定向之前页面
    return <Navigate to="/home" replace state={{ from: location }} />;
  }
  return props.children
};

export default ProtectedRoute;

接下来,我们可以再次从 React Router 的位置获取上一页的状态。当登录发生时,我们可以使用上一页将用户重定向到此所需页面。如果此页面从未设置为状态,则默认为“B”页面:

const AuthProvider = ({ children }) => {
  const [token, setToken] = useState(null);
  const navigate = useNavigate() // 跳转
  const location = useLocation() //获取上一页的状态

  const handleLogin = usecallback(async () => {
     const token = await 请求数据(用到redux或者mobx);
    setToken(token);
    const origin = location.state?.from?.pathname || '/b';
    navigate(origin);
  },[location.state?.from?.pathname, navigate])
  ...
};

over

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值