Heim  >  Fragen und Antworten  >  Hauptteil

Erstellen geschützter Routen: eine Anleitung mit React-Router-Dom

<p>So verwenden Sie <code>react-router-dom</code>, um eine geschützte Route zu erstellen und die Antwort in localStorage zu speichern, damit der Benutzer seine Details beim nächsten Öffnen erneut anzeigen kann. Nach der Anmeldung sollten sie zur Dashboard-Seite weitergeleitet werden. </p> <p>Alle Funktionen werden in ContextApi hinzugefügt.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 } aus „react-router-dom“; import About from „./About“; Dashboard aus „./Dashboard“ importieren; Login importieren von „./Login“; importiere PageNotFound aus „./PageNotFound“; Funktion Routes() { const { authLogin } = useContext(globalC); console.log("authLogin", authLogin); zurückkehren ( <BrowserRouter> <Schalter> {authLogin ? ( <> <Route path="/dashboard" Component={Dashboard} Exact /> <Exakter Pfad zur Route="/About" Component={About} /> </> ) : ( <Route path="/" Component={Login} Exact /> )} <Route Component={PageNotFound} /> </Schalter> </BrowserRouter> ); } Standardrouten exportieren;</pre> <p>上下文页面</p> <pre class="brush:php;toolbar:false;">import React, { Component, createContext } from "react"; Axios aus „axios“ importieren; export const globalC = createContext(); Die Exportklasse Gprov erweitert Component { Zustand = { authLogin: null, authLoginerror: null }; ComponentDidMount() { var localData = JSON.parse(localStorage.getItem("loginDetail")); if (localData) { this.setState({ authLogin: localData }); } } loginData = async () => { let payload = { Token: „ctz43XoULrgv_0p1pvq7tA“, Daten: { Name: „nameFirst“, E-Mail: „internetEmail“, Telefon: „phoneHome“, _Wiederholung: 300 } }; warte auf Axios .post(`https://app.fakejson.com/q`, Nutzlast) .then((res) => { if (res.status === 200) { this.setState({ authLogin: res.data }); localStorage.setItem("loginDetail", JSON.stringify(res.data)); } }) .catch((err) => this.setState({ authLoginerror: Fehler }) ); }; render() { // console.log(localStorage.getItem("loginDetail")); zurückkehren ( <globalC.Provider Wert={{ ...Dieser Staat, loginData: this.loginData }} > {this.props.children} </globalC.Provider> ); } }</pre> <p><br /></p>
P粉596191963P粉596191963394 Tage vor420

Antworte allen(2)Ich werde antworten

  • P粉253518620

    P粉2535186202023-08-25 09:42:47

    对于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

    Antwort
    0
  • P粉505917590

    P粉5059175902023-08-25 00:11:28

    问题

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

    Antwort
    0
  • StornierenAntwort