簡體   English   中英

檢查是否已登錄 - React Router App ES6

[英]Check if Logged in - 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>
      );
   }

網絡上的所有示例都使用 ES5 代碼或舊版本的 react-router(早於版本 2),我對 mixins(已棄用)和 willTransitionTo(從未被調用)的各種嘗試都失敗了。

如何設置全局“攔截器功能”以強制用戶在登陸他們請求的頁面之前進行身份驗證?

每個路由都有一個 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();
}

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

這個版本的 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 之間的 react-router 重定向差異的鏈接是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>
  );
}

這不是一個安全的解決方案
您可以嘗試在每個需要登錄的頁面上使用 useEffect 鈎子:

useEffect(() => {
  const token = localStorage.getItem('token');
  if(!token) {
    history.push('/login');
  }
}

這使用來自“react-router-dom”的 useHistory 鈎子
你只需要在調用它之前初始化它:

const history = useHistory();

如上所述,它不是一種安全的語言,而是一種簡單的語言

如果您使用的是 react-router 4 及更高版本,請使用 Render props 和 redirect 來解決這個問題。 參考: onEnter 未在 React-Router 中調用

我嘗試使用onEnter但沒有用,我發現了這一點。 在 React-Router 中未調用 onEnter

這對我有用https : //reactrouter.com/web/api/Redirect

應用程序.js

import { Redirect } from 'react-router';
.....

    <Route exact path='/' render={() => (loggedIn() ? (<Home/>) : (<Redirect to="/LogIn" />))}/>
 <Route path='/LogIn' component={LogIn} />

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM