创建受保护路由的指南:使用react-router-dom实现保护性路由
P粉011684326
P粉011684326 2023-08-23 10:07:33
0
2
494
<p>如何使用<code>react-router-dom</code>创建受保护的路由,并将响应存储在localStorage中,以便用户下次打开时可以再次查看他们的详细信息。登录后,他们应该重定向到仪表板页面。</p> <p>所有功能都在ContextApi中添加。</p> <p>Codesandbox链接:Code</p> <p>我尝试过,但未能实现。</p>

路由页面

<pre class="brush:php;toolbar:false;">从“react”导入 React, { useContext }; 从“./context”导入{globalC}; 从“react-router-dom”导入{路由、交换机、BrowserRouter}; 从“./About”导入关于; 从“./Dashboard”导入仪表板; 从“./Login”导入登录名; 从“./PageNotFound”导入PageNotFound; 函数路线(){ const { authLogin } = useContext(globalC); console.log("authLogin", authLogin); 返回 ( <浏览器路由器> <开关> {验证登录? ( <> <路线路径=“/仪表板”组件= {仪表板}精确/> /> <路线确切路径=“/关于”组件= {关于} /> </> ) : ( <路由路径=“/”组件={登录}精确/>> )} <路由组件={PageNotFound} /> </切换> </浏览器路由器> ); } 导出默认路由;</pre>

上下文页面

从“react”导入 React, { Component, createContext };
从“axios”导入 axios;

导出 const globalC = createContext();

导出类 Gprov 扩展组件 {
  状态={
    授权登录:空,
    authLogin错误:空
  };
  组件DidMount() {
    var localData = JSON.parse(localStorage.getItem("loginDetail"));
    如果(本地数据){
      this.setState({
        authLogin:本地数据
      });
    }
  }

  登录数据 = async() => {
    让有效负载= {
      令牌:“ctz43XoULrgv_0p1pvq7tA”,
      数据: {
        名称:“名字第一”,
        电子邮件:“互联网电子邮件”,
        电话:“电话首页”,
        _重复:300
      }
    };
    等待 axios
      .post(`https://app.fakejson.com/q`,有效负载)
      .then((res) => {
        if (res.status === 200) {
          this.setState({
            authLogin:res.data
          });
          localStorage.setItem("loginDetail", JSON.stringify(res.data));
        }
      })
      .catch((错误) =>
        this.setState({
          授权登录错误:错误
        })
      );
  };
  使成为() {
    // console.log(localStorage.getItem("loginDetail"));
    返回 (
      
        {this.props.children}
      
    );
  }
}</pre>
<p><br />></p>            
P粉011684326
P粉011684326

全部回复(2)
P粉968008175

对于v6:

import { Routes, Route, Navigate } from "react-router-dom";

function App() {
  return (
    <Routes>
      <Route path="/public" element={<PublicPage />} />
      <Route
        path="/protected"
        element={
          <RequireAuth redirectTo="/login">
            <ProtectedPage />
          </RequireAuth>
        }
      />
    </Routes>
  );
}

function RequireAuth({ children, redirectTo }) {
  let isAuthenticated = getAuth();
  return isAuthenticated ? children : <Navigate to={redirectTo} />;
}

链接到文档: https://gist.github.com/mjackson/d54b40a094277b7afdd6b81f51a0393f

P粉562845941

问题

<BrowserRouter>
  <Switch>
    {authLogin ? (
      <>
        <Route path="/dashboard" component={Dashboard} exact />
        <Route exact path="/About" component={About} />
      </>
    ) : (
      <Route path="/" component={Login} exact />
    )}

    <Route component={PageNotFound} />
  </Switch>
</BrowserRouter>

Switch除了RouteRedirect组件之外,不处理任何其他渲染。如果您想要像这样“嵌套”,那么您需要将每个组件包装在通用路由中,但这是完全不必要的。

您的登录组件也没有处理重定向回原始访问的“主页”或私有路由。

解决方案

react-router-dom v6

在版本6中,自定义路由组件已经不再受欢迎,首选方法是使用auth布局组件。

import { Navigate, Outlet } from 'react-router-dom';

const PrivateRoutes = () => {
  const location = useLocation();
  const { authLogin } = useContext(globalC);

  if (authLogin === undefined) {
    return null; // 或者加载指示器/旋转器等
  }

  return authLogin 
    ? <Outlet />
    : <Navigate to="/login" replace state={{ from: location }} />;
}

...

<BrowserRouter>
  <Routes>
    <Route path="/" element={<PrivateRoutes />} >
      <Route path="dashboard" element={<Dashboard />} />
      <Route path="about" element={<About />} />
    </Route>
    <Route path="/login" element={<Login />} />
    <Route path="*" element={<PageNotFound />} />
  </Routes>
</BrowserRouter>

或者

const routes = [
  {
    path: "/",
    element: <PrivateRoutes />,
    children: [
      {
        path: "dashboard",
        element: <Dashboard />,
      },
      {
        path: "about",
        element: <About />
      },
    ],
  },
  {
    path: "/login",
    element: <Login />,
  },
  {
    path: "*",
    element: <PageNotFound />
  },
];

...

export default function Login() {
  const location = useLocation();
  const navigate = useNavigate();
  const { authLogin, loginData } = useContext(globalC);

  useEffect(() => {
    if (authLogin) {
      const { from } = location.state || { from: { pathname: "/" } };
      navigate(from, { replace: true });
    }
  }, [authLogin, location, navigate]);

  return (
    <div
      style={{ height: "100vh" }}
      className="d-flex justify-content-center align-items-center"
    >
      <button type="button" onClick={loginData} className="btn btn-primary">
        登录
      </button>
    </div>
  );
}

react-router-dom v5

创建一个消费您的auth上下文的PrivateRoute组件。

const PrivateRoute = (props) => {
  const location = useLocation();
  const { authLogin } = useContext(globalC);

  if (authLogin === undefined) {
    return null; // 或者加载指示器/旋转器等
  }

  return authLogin ? (
    <Route {...props} />
  ) : (
    <Redirect
      to={{
        pathname: "/login",
        state: { from: location }
      }}
    />
  );
};

更新您的Login组件以处理重定向回原始访问的路由。

export default function Login() {
  const location = useLocation();
  const history = useHistory();
  const { authLogin, loginData } = useContext(globalC);

  useEffect(() => {
    if (authLogin) {
      const { from } = location.state || { from: { pathname: "/" } };
      history.replace(from);
    }
  }, [authLogin, history, location]);

  return (
    <div
      style={{ height: "100vh" }}
      className="d-flex justify-content-center align-items-center"
    >
      <button type="button" onClick={loginData} className="btn btn-primary">
        登录
      </button>
    </div>
  );
}

将所有路由呈现为“平面列表”

function Routes() {
  return (
    <BrowserRouter>
      <Switch>
        <PrivateRoute path="/dashboard" component={Dashboard} />
        <PrivateRoute path="/About" component={About} />
        <Route path="/login" component={Login} />
        <Route component={PageNotFound} />
      </Switch>
    </BrowserRouter>
  );
}

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!