创建受保护的路由:使用react-router-dom的方法指南
P粉596191963
P粉596191963 2023-08-24 11:22:28
0
2
323
<p>如何使用<code>react-router-dom</code>创建一个受保护的路由,并将响应存储在localStorage中,以便用户下次打开时可以再次查看他们的详细信息。登录后,他们应该重定向到仪表盘页面。</p> <p>所有功能都添加在ContextApi中。 Codesandbox链接:Code</p> <p>我尝试过,但无法实现</p> <p>路由页面</p> <pre class="brush:php;toolbar:false;">import React, { useContext } from "react"; import { globalC } from "./context"; import { Route, Switch, BrowserRouter } from "react-router-dom"; import About from "./About"; import Dashboard from "./Dashboard"; import Login from "./Login"; import PageNotFound from "./PageNotFound"; function Routes() { const { authLogin } = useContext(globalC); console.log("authLogin", authLogin); return ( &lt;BrowserRouter&gt; &lt;Switch&gt; {authLogin ? ( &lt;&gt; &lt;Route path="/dashboard" component={Dashboard} exact /&gt; &lt;Route exact path="/About" component={About} /&gt; &lt;/&gt; ) : ( &lt;Route path="/" component={Login} exact /&gt; )} &lt;Route component={PageNotFound} /&gt; &lt;/Switch&gt; &lt;/BrowserRouter&gt; ); } export default Routes;</pre> <p>上下文页面</p> <pre class="brush:php;toolbar:false;">import React, { Component, createContext } from "react"; import axios from "axios"; export const globalC = createContext(); export class Gprov extends Component { state = { authLogin: null, authLoginerror: null }; componentDidMount() { var localData = JSON.parse(localStorage.getItem("loginDetail")); if (localData) { this.setState({ authLogin: localData }); } } loginData = async () =&gt; { let payload = { token: "ctz43XoULrgv_0p1pvq7tA", data: { name: "nameFirst", email: "internetEmail", phone: "phoneHome", _repeat: 300 } }; await axios .post(`https://app.fakejson.com/q`, payload) .then((res) =&gt; { if (res.status === 200) { this.setState({ authLogin: res.data }); localStorage.setItem("loginDetail", JSON.stringify(res.data)); } }) .catch((err) =&gt; this.setState({ authLoginerror: err }) ); }; render() { // console.log(localStorage.getItem("loginDetail")); return ( &lt;globalC.Provider value={{ ...this.state, loginData: this.loginData }} &gt; {this.props.children} &lt;/globalC.Provider&gt; ); } }</pre> <p><br /></p>
P粉596191963
P粉596191963

Antworte allen(2)
P粉505917590

问题

<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>
  );
}

Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!