我想使用react和reach router完成登录。本质上,在成功认证后,我想从Login Component转到HomeLayout Component。我已经成功登录
这是我的App组件的代码,这是项目的入口点
import React, { Component } from 'react';
function App() {
return (
<div>
<Login />
</div>
);
}
===============
登录组件
import React, { Component } from "react";
import axios from "axios"
class Login extends Component {
state = {
username: "",
password: "",
loggedIn: false
}
onChange = (e) => {
e.preventDefault()
this.setState({
[e.target.name]:e.target.value
})
}
LoginUser = (e)=>{
const {username, password} = this.state
e.preventDefault()
let UserLoginDetails = {
email: username,
password: password
}
axios.post("localhost:4500/users/login", UserLoginDetails)
.then(loginResultFromBackend=>{
this.setState({loggedIn: true})
// I want to go to "/Home" here
}).catch(error=>{
console.log(error)
})
}
render() {
return (
<form onSubmit={this.LoginUser}>
<input
type="text"
value={this.state.username}
name="username"
onChange={this.onChange}/>
<input
type="text"
value={this.state.username}
name="username"
onChange={this.onChange}/>
<button type="submit">Submit</button>
</form>
);
}
}
===========================
家庭组件
import category from "./category";
import { Router, Link } from "@reach/router";
import NotFound404 from "../default404/PageNotFound";
class HomeLayout extends Component {
render() {
return (
<div>
<Link to={`Home`} > Home </Link>
<Link to={`category`} Categories </Link>
<Router>
<Home path="/Home"></Home>
<category path={`category/:category`}></category>
<NotFound404 default />
</Router>
</div>
);
}
}
在该状态下,我已经设置了username =“”,password =“”,并且loginIn = false。
预期行为
从后端获得结果后,我想导航到/ Home上的Home页面。
我尝试做navigate("/Home")
,但这只是更改了URL,而没有更改组件。
在这里帮我吗?如果从反应路由器方面来的人有所了解,那将很有用,因为我本质上是代码新手。
答案 0 :(得分:1)
import { Redirect } froom "react-router-dom";
render() {
if (this.state.loggedIn) return <Redirect to="/Home" />;
return (
<form onSubmit={this.LoginUser}>
<input
type="text"
value={this.state.username}
name="username"
onChange={this.onChange}/>
<input
type="text"
value={this.state.username}
name="username"
onChange={this.onChange}/>
<button type="submit">Submit</button>
</form>
);
}
答案 1 :(得分:0)
如果react-router-dom
为true,则从this.state.loggedIn
导入重定向组件,并使用它来重定向到主页。您可以在react-router-dom
和“到达”路由器上使用它。
答案 2 :(得分:0)
如果“ 登录”组件用作
,则可以直接使用this.props.history.push("/Home");
<Switch>
<Route path="/Login" component={Login} />
<Route path="/Home" component={Home} />
</Switch>
因此,您可以将其写为
axios.post("localhost:4500/users/login", UserLoginDetails)
.then(loginResultFromBackend=>{
this.setState({loggedIn: true})
this.props.history.push("/Home");
}).catch(error=>{
console.log(error)
})
此外,您可以尝试使用LINK
中提到的useHistory
答案 3 :(得分:0)
这是你的做法。我将使用 2 个 React Hook 分享它:
useEffect
来实现着陆效果):import { navigate, useLocation } from "@reach/router";
import { useCallback } from "react";
import { useAuth } from "../auth";
import { routes } from "../utilities";
/**
* This can be passed as a prop vs using a const in case you have multiple paths
* you'd like to redirect it to, but let's keep it simple.
* we w
*/
// routes.login =>7 "/login"
const LOGIN_PATH = routes.login;
/**
* This will redirect you to a login page and will pass
* a "redirect" query param so you can redirect the user later.
*/
type GoToLoginProps = {
callbackIfAuthenticated?(): void;
};
export function useGoToLogin(props?: GoToLoginProps) {
/**
* This can be extracted or omitted. THis simply checks if
* the user is authenticated or not. I have defined a useAuth hook
* that uses React context to handle all of the authentication.
*
* This is not defined in this post.
* You can also pass this as a prop (if you want to make the hook
* pure - e.g: no internal dependencies)
*/
const { authenticated } = useAuth();
// The <Location></Location> component must be passed at the top of the
// Component tree as it uses React.Context
const location = useLocation();
// Note, "redirect" will be used in useRedirect hook. You can create this
// as a const variable.
const loginBack = `?redirect=${location.pathname}`;
const callbackIfAuthenticated = props?.callbackIfAuthenticated;
return useCallback(() => {
if (authenticated) {
callbackIfAuthenticated?.();
return;
}
navigate(LOGIN_PATH + loginBack);
}, [authenticated, loginBack, callbackIfAuthenticated]);
}
import { navigate, useLocation } from "@reach/router";
import { useCallback, useMemo } from "react";
/**
* This will redirect a user from a path to something else.
*
* Be very careful on allowing any redirects as you can let the user
* be exposed to an Open Redirect Vulnerability. Always try to redirect using
* local or whitelisted urls!
*
* I am going to be sharing this with local URLs only!
*/
type RedirectProps = {
defaultPath: string;
};
export function useRedirect(props?: RedirectProps) {
// The <Location></Location> component must be passed at the top of the
// Component tree as it uses React.Context
const { search } = useLocation();
const params = useMemo(() => new URLSearchParams(search), [search]);
const defaultPath = props?.defaultPath;
return useCallback(() => {
const redirect = params.get("redirect");
// If it doesn't exist, then exit the function.
if (!redirect || !verifyLocalUrl(redirect)) {
defaultPath && navigate(defaultPath);
return;
}
// The dot (.) symbolizes relativeness to the base path "/"
navigate("." + redirect);
}, [params, defaultPath]);
}
/**
*
* I am no security expert, so I don't know which are the problems with this approach.
* We make a simple, yet powerful check which will verify if the
* user has a malicious intent and has sent a full URL within the login.
* (Open Redirect Attacks).
*
* We check if the verifyLocalUrl is an URL. If it is, then it WON'T throw.
* If it isn't it will throw a TypeError and we can safely assume it's not a url.
*
* In addition, we also check if the URL has a dot (.) because malformed URLs such as
* "mybadsite.se" are still valid and will fail the URL check.
* @param redirect
* @returns
*/
function verifyLocalUrl(redirect: string) {
try {
if (redirect?.indexOf(".") !== -1) {
return false;
}
new URL(redirect);
return false;
} catch (e) {
return true;
}
}
然后,您将如何使用它们:
第一。如果未通过身份验证,您希望将它们重定向到的页面中。
const test = useCallback(() => window.alert("Put any function you'd like to execute in case the user is authenticated"), []);
const bookConsult = useGoToLogin({ callbackIfAuthenticated: test });
<button onClick={bookConsult}>Proceed If Authenticated - Book Consult</button>
然后,在您的登录组件中:
export const Login = () => {
const auth = useAuth();
const redirect = useRedirect({ defaultPath: "/" });
const login = async (values) => {
const loginResult = auth.login(values.username, values.password);
if(loginResult.error) {
return;
}
redirect();
}
return (
<>
{/**Login here */}
<button onClick={login}>Login </button>
</>
)
}
<LocationProvider></LocationProvider>
:function App() {
return (
<LocationProvider>
<Root />
</LocationProvider>);
}