登录时重定向-React.js

时间:2018-08-19 20:07:19

标签: javascript reactjs react-router react-router-dom

我正在尝试在用户成功登录(在Login.js内)后使用React Router进行简单的重定向,并阻止用户重新访问登录页面(在index.js内)。

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

在index.js中,我有一个条件可以测试用户是否已登录,并(较差)警告用户为什么他们无法访问所需页面。我在YouTube视频中看到了这一点,但不确定这是否是获得理想效果的最佳方法。

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

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

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="you@email.com" />
                </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组件

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

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;

5 个答案:

答案 0 :(得分:2)

要解决您的问题,您必须为Login / Register创建单独的组件,并根据用户的需要发出警报和重定向。您将需要withRouter库中名为react-router的高阶组件。

登录容器

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)

然后像下面这样在您的Routes中使用它:

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

Register相同,或者您可以制作一个并获得alertMessageredirectTo之类的参数,并使用它们代替硬编码值。

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

我更喜欢使用新的上下文API来共享用户,本地化等实体,因此这里是一个示例,说明如何使用React PrivateRoute API来制作Context

App.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

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

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

import PrivateRoute from './PrivateRoute'

...

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

希望有帮助!祝你好运!

答案 1 :(得分:2)

如果有人仍在寻找另一个答案,则可以执行以下操作:

 public static void main(String[] args) throws Exception {


           JSONParser jsonparser = new JSONParser();
           try( FileReader reader = new FileReader("test.json"))
           {
            Object obj = jsonparser.parse(reader);
            ObjectMapper mapper = new ObjectMapper();
            JSONArray List = (JSONArray) obj;
            JsonNode root = mapper.readTree(reader);
            for (JsonNode jsonNode : root) {
                if (jsonNode instanceof ObjectNode) {
                    ObjectNode o = (ObjectNode) jsonNode;
                    o.remove("UserID");
                }
            }
            System.out.println(List);                          
        }
           catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ParseException e) {
                e.printStackTrace();
            }                    
     }

注意:为简便起见,我删除了不相关的代码。在此示例中,成功的LOGIN api调用中,返回的响应正文包含import { Redirect } from 'react-router-dom'; render() { let isSuccess, message; if (this.props.response.hasOwnProperty('response')) { message = this.props.response.response.data.message; console.log(this.props); isSuccess = this.props.response.response.data.success; if (isSuccess) { localStorage.setItem('jwt', JSON.stringify(this.props.response.response.data.token)); } } return ( <div> {!isSuccess ? <div>{message}</div> : <Redirect to='/admin/dashboard' />} </div> ); } ,在失败的LOGIN api调用中,返回的响应正文包含{ success: true, token: <jwt> }

答案 2 :(得分:1)

如官方文档所述,您应该创建一个专用路由器

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

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

要了解更多信息,请点击链接https://reacttraining.com/react-router/web/example/auth-workflow

答案 3 :(得分:0)

您可以使用:

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

答案 4 :(得分:0)

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