web-dev-qa-db-ja.com

ログイン時のリダイレクト-React.js

ユーザーが(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!_がオフに設定されますが、ログインが成功した直後にアラートをオフにしたくないので、最初にリダイレクトをトリガーします。括弧内の2つを入れ替えると、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="[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コンポーネント

_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;
_
3
douglasrcjames

問題を解決するには、Login/Registerの個別のコンポーネントを作成し、ユーザーに応じてアラートとリダイレクトを行う必要があります。 react-router libのwithRouterという高次コンポーネントが必要です。

ログインコンテナ

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

それが役に立てば幸い!幸運を!

3
Denys Kotsur

以下を使用できます。

<Redirect Push to="/somewhere/else"/>
2
Olusola Omosola

公式ドキュメントが言うように、プライベートルーターを作成する必要があります

これは、ローカルストレージを使用してユーザーデータが存在するかどうかを確認するために実装する方法の例です。データがない場合は、ログインページにリダイレクトされます。これはすべてのコンポーネントで再利用できます!

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

0
jerryurenaa