web-dev-qa-db-ja.com

ログインしているかどうかを確認します-React Router App ES6

react-router(v2.8.1)およびES6構文を使用してReact。jsアプリケーション(v15.3)を作成しています。ユーザーが最初にログインする必要があるかどうかを確認するために、ページ間のすべての遷移をインターセプトするルーターコードを取得できません。

私のトップレベルのレンダリング方法は非常に簡単です(アプリも簡単です):

 render()
   {
      return (
         <Router history={hashHistory}>
            <Route path="/" component={AppMain}>
               <Route path="login" component={Login}/>
               <Route path="logout" component={Logout}/>
               <Route path="subject" component={SubjectPanel}/>
               <Route path="all" component={NotesPanel}/>
            </Route>
         </Router>
      );
   }

Web上のすべてのサンプルはES5コードまたは古いバージョンのreact-router(バージョン2より古い)を使用しており、mixin(非推奨)およびwillTransitionTo(呼び出されない)でのさまざまな試みは失敗しました。

グローバルな「インターセプター機能」を設定して、ユーザーが要求したページに到達する前にユーザーに強制的に認証させるにはどうすればよいですか?

17

OnEnterコールバックのこのバージョンは、react-router(v2.8)で最終的に機能しました。

 requireAuth(nextState,
               replace)
   {
      if(!this.authenticated()) // pseudocode - SYNCHRONOUS function (cannot be async without extra callback parameter to this function)
         replace('/login')
   }

V1とv2のリアクションルーターリダイレクトの違いを説明するリンクは here です。以下に引用した関連セクション:

Likewise, redirecting from an onEnter hook now also uses a location descriptor.

// v1.0.x
(nextState, replaceState) => replaceState(null, '/foo')
(nextState, replaceState) => replaceState(null, '/foo', { the: 'query' })

// v2.0.0
(nextState, replace) => replace('/foo')
(nextState, replace) => replace({ pathname: '/foo', query: { the: 'query' } })

以下の完全なコードリスト(react-routerバージョン2.8.1):

requireAuth(nextState,
               replace)
{
   if(!this.authenticated()) // pseudocode - SYNCHRONOUS function (cannot be async without extra callback parameter to this function)
     replace('/login');
}

render() {
  return (
     <Router history={hashHistory}>
        <Route path="/" component={AppMain}>
           <Route path="login" component={Login}/>
           <Route path="logout" component={Logout}/>
           <Route path="subject" component={SubjectPanel} onEnter={this.requireAuth}/>
           <Route path="all" component={NotesPanel} onEnter={this.requireAuth}/>
        </Route>
     </Router>
  );
}
0

すべてのルートには、ルート遷移が発生する前に呼び出されるonEnterフックがあります。カスタムrequireAuth関数でonEnterフックを処理します。

<Route path="/search" component={Search} onEnter={requireAuth} />

RequireAuthのサンプルを以下に示します。ユーザーが認証された場合、next()を介して移行します。それ以外の場合、パス名を/ loginに置き換え、next()を介して移行します。ログインには現在のパス名も渡されるため、ログインが完了すると、ユーザーは最初に要求されたパスにリダイレクトされます。

function requireAuth(nextState, replace, next) {
  if (!authenticated) {
    replace({
      pathname: "/login",
      state: {nextPathname: nextState.location.pathname}
    });
  }
  next();
}
14
vijayst

V4では、使用が認証されているかどうかを確認するルートコンポーネントを作成し、次のコンポーネントを返します。もちろん、次のコンポーネントは他のルートでもかまいません。

import React, { Component } from 'react';
import PropTypes from 'prop-types';

import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { Route, Redirect } from 'react-router-dom';

import AuthMiddleware from 'modules/middlewares/AuthMiddleware';

class PrivateRoute extends Component {
  static propTypes = {
    component: PropTypes.func.isRequired,
    isAuthenticated: PropTypes.bool,
    isLoggedIn: PropTypes.func.isRequired,
    isError: PropTypes.bool.isRequired
  };

  static defaultProps = {
    isAuthenticated: false
  };

  constructor(props) {
    super(props);
    if (!props.isAuthenticated) {
      setTimeout(() => {
        props.isLoggedIn();
      }, 5);
    }
  }

  componentWillMount() {
    if (this.props.isAuthenticated) {
      console.log('authenticated');
    } else {
      console.log('not authenticated');
    }
  }
  componentWillUnmount() {}

  render() {
    const { isAuthenticated, component, isError, ...rest } = this.props;
    if (isAuthenticated !== null) {
      return (
        <Route
          {...rest}
          render={props => (
            isAuthenticated ? (
              React.createElement(component, props)
            ) : (
              <Redirect
                to={{
                  pathname: isError ? '/login' : '/welcome',
                  state: { from: props.location }
                }}
              />
            )
          )}
        />
      );
    } return null;
  }

}

const mapStateToProps = (state) => {
  return {
    isAuthenticated: state.auth.isAuthenticated,
    isError: state.auth.isError
  };
};

const mapDispatchToProps = (dispatch) => {
  return bindActionCreators({
    isLoggedIn: () => AuthMiddleware.isLoggedIn()
  }, dispatch);
};

export default connect(mapStateToProps, mapDispatchToProps)(PrivateRoute);
4
eersteam