使用react-router-dom创建安全路由
P粉156983446
P粉156983446 2023-09-21 15:38:12
0
2
378

如何使用react-router-dom创建一个受保护的路由,并将响应存储在localStorage中,以便用户下次打开时可以再次查看其详细信息。登录后,应重定向到仪表板页面。

所有功能都添加在ContextApi中。

Codesandbox链接:Code

我尝试过,但无法实现。

路由页面

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 (
    <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>
  );
}
export default Routes;

上下文页面

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 () => {
    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) => {
        if (res.status === 200) {
          this.setState({
            authLogin: res.data
          });
          localStorage.setItem("loginDetail", JSON.stringify(res.data));
        }
      })
      .catch((err) =>
        this.setState({
          authLoginerror: err
        })
      );
  };
  render() {
    // console.log(localStorage.getItem("loginDetail"));
    return (
      <globalC.Provider
        value={{
          ...this.state,
          loginData: this.loginData
        }}
      >
        {this.props.children}
      </globalC.Provider>
    );
  }
}

P粉156983446
P粉156983446

全部回复(2)
P粉587780103

问题


  
    {authLogin ? (
      <>
        
        
      
    ) : (
      
    )}

    
  

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

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

解决方案

react-router-dom v6

在版本6中,自定义路由组件已经不再流行,推荐的方法是使用身份验证布局组件。

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

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

  if (authLogin === undefined) {
    return null; // or loading indicator/spinner/etc
  }

  return authLogin 
    ? 
    : ;
}

...


  
    } >
      } />
      } />
    
    } />
    } />
  

或者

const routes = [
  {
    path: "/",
    element: ,
    children: [
      {
        path: "dashboard",
        element: ,
      },
      {
        path: "about",
        element: 
      },
    ],
  },
  {
    path: "/login",
    element: ,
  },
  {
    path: "*",
    element: 
  },
];

...

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

react-router-dom v5

创建一个消费您的身份验证上下文的PrivateRoute组件。

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

  if (authLogin === undefined) {
    return null; // or loading indicator/spinner/etc
  }

  return authLogin ? (
    
  ) : (
    
  );
};

更新您的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 (
    
); }

在“平面列表”中渲染所有路由

function Routes() {
  return (
    
      
        
        
        
        
      
    
  );
}

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