javascript 登录时重定向 - React.js

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/51921419/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 09:45:06  来源:igfitidea点击:

Redirect on Login - React.js

javascriptreactjsreact-routerreact-router-dom

提问by douglasrcjames

I am trying to do a simple Redirect with React Router after my user successfully logs in (inside Login.js), and prevent the user from revisiting the login page (inside index.js).

在我的用户成功登录(在 Login.js 内)后,我试图用 React Router 做一个简单的重定向,并防止用户重新访问登录页面(在 index.js 内)。

In Login.js, I have onSubmit={this.handleSubmit}within the login button tag, and handleSubmit(e)function to Redirect. I have tried a few other solutions online, but I think my understanding on the usage of the <Redirect/>component is wrong.

在 Login.js 中,我onSubmit={this.handleSubmit}在登录按钮标记中handleSubmit(e)具有重定向功能。我在网上尝试了一些其他的解决方案,但我认为我对<Redirect/>组件用法的理解是错误的。

In index.js, I have a conditional that tests if the user is signed in, or not signed in, and (poorly) alerts the user on why they can't visit the desired page. I saw this in a Youtube video, but not sure if it's the best way to get the desired effect.

在 index.js 中,我有一个条件来测试用户是登录还是未登录,并且(很差地)提醒用户为什么他们无法访问所需的页面。我在 Youtube 视频中看到了这一点,但不确定这是否是获得所需效果的最佳方式。

Currently, when I log in successfully, the alert You can't login if you are logged in!is set off, but I obviously don't want the alert going off right after a successful login, I want the Redirect to trigger first. If I swap the two in the parenthesis, React throws an error.

目前,当我成功登录时,警报会You can't login if you are logged in!被触发,但我显然不希望在成功登录后立即触发警报,我希望首先触发重定向。如果我交换括号中的两个,React 会抛出错误。

How do I get the Redirect to trigger right after a successful login, but not send the alert You can't login if you are logged in!?

如何在成功登录后立即触发重定向,但不发送警报You can't login if you are logged in!

Login.js Component:

Login.js 组件

import React, { Component } from 'react';
import fire from '../config/Fire.js';
import { Link, Redirect } from 'react-router-dom';
import PasswordMask from 'react-password-mask';

export default class Login extends Component {
    constructor(props) {
        super(props);
        this.login = this.login.bind(this);
        this.handleChange = this.handleChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.signup = this.signup.bind(this);
        this.state = {
          email: '',
          password: ''
        };
      }

    handleChange(e) {
        this.setState({ [e.target.name]: e.target.value });
    }

    handleSubmit(e) {
        e.preventDefault();
        <Redirect to="/ticket-list"/>;
    }

    login(e) {
        e.preventDefault();
        fire.auth().signInWithEmailAndPassword(this.state.email, this.state.password).catch((error) => {
            alert(error);
            });
    }

    signup(e){
        e.preventDefault();
        fire.auth().createUserWithEmailAndPassword(this.state.email, this.state.password).catch((error) => {
            alert(error);
            })
    }

    render() {
        return (
        <div className="m-container">
            <h1>Login</h1>
            <hr/>
            <div className="m-container">
                <form onSubmit={this.submitForm}>
                <div>
                    <label for="exampleInputEmail1">Email address: </label>
                    <br/>
                    <input 
                    value={this.state.email} 
                    onChange={this.handleChange} 
                    type="text" 
                    name="email" 
                    id="exampleInputEmail1" 
                    placeholder="[email protected]" />
                </div>
                <div>
                    <label for="exampleInputPassword1">Password: </label>
                    <br/>
                    {/* Margin issue when showing and hiding password */}
                    <PasswordMask 
                    value={this.state.password} 
                    onChange={this.handleChange} 
                    type="password" 
                    name="password" 
                    id="exampleInputPassword1" 
                    placeholder="**********"
                     />
                </div>
                <br/>
                <button 
                    type="submit" 
                    className="button" 
                    onClick={this.login}
                    onSubmit={this.handleSubmit}>Login</button>
                &nbsp;
                <Link className="button-inv" to="/register">Register</Link>
                </form>
            </div>
        </div>
        );
    }
}

index.js Component:

index.js 组件

import React, { Component } from 'react';
import { Route, Switch, Redirect } from 'react-router-dom';

import Home from './Home';
import Technician from './Technician';
import About from './About';
import Register from './Register';
import Login from './Login';
import TicketList from './TicketList';

export default class Routes extends Component {

    render() {
        return (
        <Switch>
            <Route path="/" exact component={Home} />
            <Route path="/technician" exact component={Technician} />
            <Route path="/about" exact component={About} />
            <Route path="/register" exact render={()=>(
                this.props.user ? (alert("You can't register if you are logged in!"), (<Redirect to="/"/>)) : (<Register/>)
            )} />
            <Route path="/login" exact render={()=>(
                this.props.user ? (alert("You can't login if you are logged in!"), (<Redirect to="/ticket-list"/>)) : (<Login/>)
            )} />
            <Route path="/ticket-list" exact render={()=>(
                this.props.user ? (<TicketList/>) : (alert("You must log in to visit this page."), (<Redirect to="/login"/>))
            )} />
        </Switch>
        );
    }
};

App.js:

应用程序.js

import React, { Component } from 'react';
import { BrowserRouter } from 'react-router-dom';
import Routes from './routes';
import fire from './config/Fire.js';

// CSS
import './assets/css/App.css';
import './assets/css/Header.css';
import './assets/css/Footer.css';
// Components
import Header from './components/Header';
import Footer from './components/Footer';

class App extends Component {
  constructor(props){
    super(props);
    this.state = {
      user:{},
    }
  }

  //When component is done rendering for the first time
  componentDidMount(){
    this.authListener();
  }

  // If user logs in (if) or out (else) this is called
  authListener() {
    fire.auth().onAuthStateChanged((user) => {
      //console.log(user);
      if (user) {
        this.setState({ user });
      } else {
        this.setState({ user: null });
      }
    });
  }


  render() {
    return (
      <BrowserRouter>
        <div className="wrapper">
          <Header user={this.state.user} />
          <div className="body">
            <Routes user={this.state.user} />
          </div>
          <Footer />
        </div>
      </BrowserRouter>
    );
  }
}

export default App;

采纳答案by Denys Kotsur

To solve your problem you have to create separate components for Login/Registerand make alerts and redirects there depends on user. You will need High Order Component named withRouterfrom react-routerlib.

要解决您的问题,您必须为Login/创建单独的组件,Register并根据用户进行警报和重定向。您将需要withRouterreact-routerlib命名的高阶组件。

Login container:

登录容器

class LoginContainer extends Component {
  constructor(props) {
    super(props)

    if (props.user) {
      alert("You can't login if you are logged in!")
      props.history.push('/ticket-list')
    }
  }

  render() {
    return <Login />;
  }
}

export default withRouter(LoginContainer)

And then use it in your Routeslike this:

然后Routes像这样使用它:

<Route path="/login" render={()=> <LoginContainer user={this.props.user} />} />

The same one for Registeror you can just make one and get params like alertMessageand redirectToand use them instead of hardcoded values.

相同的Register或者你可以只制作一个并获得像alertMessage和这样的参数,redirectTo并使用它们而不是硬编码值。

In addition, I advice you to use auth HoC for your private routes, which is not accessible without authentication.

此外,我建议您将 auth HoC 用于您的私有路由,未经身份验证无法访问。

I'd prefer to use new context API for sharing such entity as user, localization, etc, so here is an example how to make PrivateRouteusing React ContextAPI.

我更喜欢使用新的上下文 API 来共享用户、本地化等实体,所以这里是一个如何PrivateRoute使用 React ContextAPI进行制作的示例。

App.js

应用程序.js

...
export const UserContext = React.createContext();
...
class App extends Component {

    state = {
        user: null
    }

    componentDidMount() {
      this.authListener();
    }

    authListener() {
      fire.auth().onAuthStateChanged(user => {
        if (user) {
          this.setState({ user });
        }
      });
    }

    render() {
       <UserContext.Provider value={this.state}>
           <BrowserRouter>
               // another things Switch etc
               ...
           </BrowserRouter>
       </UserContext.Provider>
    }
}

PrivateRoute.jsx

私有路由.jsx

import React, { Component } from 'react';
import { Route, Redirect } from 'react-router-dom'
import { UserContext } from './App'

const PrivateRoute = ({ component: ComposedComponent, ...rest }) => {

  class Authentication extends Component {

    handleRender = props => {
      if (!this.props.user) {
        return <Redirect to="/login" />
      } else {
        return <ComposedComponent user={this.props.user} {...props} />
      }
    }

    render() {
      return (
        <Route {...rest} render={this.handleRender} />
      );
    }
  }

  return (
    <UserContext.Consumer>
      {
        ({ user }) => <Authentication user={user} />
      }
    </UserContext.Consumer>
  )
};

export default PrivateRoute

And then you can use PrivateRouteinstead of Routein case when you don't want to show page without authentication.

然后,如果您不想在未经身份验证的情况下显示页面,则可以使用PrivateRoute代替Route

import PrivateRoute from './PrivateRoute'

...

// all of the component code
render() {
    ...
    <Switch>
        <PrivateRoute path="/ticket-list" component={<TicketList />} />
    </Switch>
    ...
}

Hope it helps! Good luck!

希望能帮助到你!祝你好运!

回答by Olusola Omosola

You can use:

您可以使用:

<Redirect push to="/somewhere/else"/>

回答by jerryurenaa

as the official documentation says, you should create a Private router

正如官方文档所说,您应该创建一个私有路由器

this is an example of how I am implementing it using local storage to see if the user data is there or not then redirecting back to the login page if the data is not there. this can be reused in all of your components!

这是我如何使用本地存储实现它的示例,以查看用户数据是否存在,然后如果数据不存在则重定向回登录页面。这可以在您的所有组件中重复使用!

import { BrowserRouter as Router, Route, Redirect, Switch } from 'react-router-dom';

import Login from './views/login';
import Supportedmodels from './views/dashboard/supported-models';


const PrivateRoute = ({ component: Component, ...rest }) => 
(  
  <Route {...rest} render={props => 
  (
    localStorage.getItem('user') ? <Component {...props} /> : <Redirect to={{pathname: '/login'}}/>
  )}/>
);

function App() 
{
  return (

    <Router>
      <Switch>
        <PrivateRoute path="/" component={Supportedmodels} exact />

        <Route path="/login" component={Login} />
      </Switch>      
    </Router>
  );
}

to read more here is the link https://reacttraining.com/react-router/web/example/auth-workflow

在这里阅读更多是链接https://reacttraining.com/react-router/web/example/auth-workflow