web-dev-qa-db-ja.com

Reactでのルーティングを防止し、ユーザーがブラウザーのタブでURLを手動で変更した場合

ユーザーがブラウザーのタブでルートを手動で変更してEnterキーを押すと発生する問題で立ち往生しています。これにより、反応ルーターはユーザーが入力した状態に移動します。これを防ぎ、自分のWebサイトのボタンクリックで実装したフローを介したルーティングのみを許可します。

一部の画面には、ユーザーが予想されるフローを使用してサイトをナビゲートした場合にのみ利用できるデータが必要です。ユーザーがURLのルートを手動で変更して特定のルートに直接移動しようとすると、目的のフローがスキップされる可能性があるため、アプリが機能しなくなります。

他のシナリオでは、一部のユーザーが一部のルートにアクセスできないように制限したいが、ユーザーはパスを知っていて手動でブラウザのURLに入力した場合、その画面が表示されますが、そうすべきではありません。

17
Vishal Gulati

前のページの小道具を使用します。その小道具が定義されていない場合(つまり、ユーザーが適切なプロセスに従わなかったことを意味します:) hehe)ユーザーをランディングページまたはどこにでも送り返すだけです。

2
Chigo Kawa

HOCを使用してルートガードを作成できます。たとえば、権限のないユーザーがルート/profileを通過しないようにするには、次のようにします。

// requireAuthorized.js (HOC)
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {connect} from 'react-redux'
import {Redirect} from 'react-router-dom'

const connector = connect(
  state => ({
    isAuthorized: state.profile !== null // say, you keep user profile in redux
  })
)

export default (WrappedComponent) => {
  return (
    connector(
      class extends Component {
        static propTypes = {
          isAuthorized: PropTypes.bool.isRequired
        }

        render () {
          const {isAuthorized, ...clearedProps} = this.props
          if (isAuthorized) {
            return <WrappedComponent {...clearedProps} />
          } else {
            return <Redirect to={{pathname: '/login'}} />
          }
        }
      }
    )
  )
}


// ProfilePage.jsx
import React from 'react'
...
import requireAdmin from '../hocs/requireAdmin' // adjust path

class ProfilePage extends React.Component {
  ...
  render () {
    return (
      <div>
        ...
      </div>
    )
  }
}

export default requireAdmin(ProfilePage)

私のProfilePage.jsのexportステートメントに注意してください

2
GProst

このようなものが適切です。認証/コンテキストプロップを処理するラップ機能でHOCルートを作成します。注:これは、メニュー項目などではなく、ルートへの直接アクセスを扱います。これは、menu/menuItemコンポーネントでも同様に扱う必要があります。

import requireAuth from "../components/login/requireAuth";

class Routes extends React.Component<RoutesProps, {}> {
    render() {
        return (
            <div>
                <Switch>
                    <Route exact={true} path="/" component={requireAuth(Persons, ["UC52_003"])} />
                    <Route path="/jobs" component={requireAuth(Jobs, ["UC52_006"])} />
                </Switch>
            </div>
        )
    }
}


export default function (ComposedComponent, privileges) {

    interface AuthenticateProps {
        isAuthenticated: boolean
        userPrivileges: string[]
    }
    class Authenticate extends React.Component<AuthenticateProps, {}> {
        constructor(props: AuthenticateProps) {
            super(props)
        }

        render() {
            return (
                isAuthorized(this.props.isAuthenticated, privileges, this.props.userPrivileges) &&
                <ComposedComponent {...this.props} /> || <div>User is not authorised to access this page.</div>
            );
        }
    }

    function mapStateToProps(state) {
        return {
            isAuthenticated: state.userContext ? state.userContext.isAuthenticated : false,
            userPrivileges: state.userContext ? state.userContext.user ? state.userContext.user.rights : [] : []
        };
    }

    return connect(mapStateToProps, null)(Authenticate);
}
1
jan

最もクリーンな解決策として this library を使用することをお勧めします(または少なくとも個人的に同様の実装を行う)。

次に、認証チェックHOCを作成します。

export const withAuth = connectedReduxRedirect({
    redirectPath: '/login',
    authenticatedSelector: state => state.user.isAuthenticated, // or whatever you use
    authenticatingSelector: state => state.user.loading,
    wrapperDisplayName: 'UserIsAuthenticated'
});

そして、フローHOCを簡単に作成できます。

export const withFlow = (step) = connectedReduxRedirect({
    redirectPath: '/initial-flow-step',
    authenticatedSelector: state => state.flow[step] === true,
    wrapperDisplayName: 'FlowComponent'
});

次に、コンポーネントを初期化します

const AuthenticatedComponent = withAuth(Dashboard)
const SecondStepComponent = withFlow("first-step-finished")(SecondStep)
const ThirdStepComponent = withFlow("second-step-finished")(ThirdStep)

HOCを構成することで、認証されたフローステップを簡単に作成できます。

const AuthSecondStepComponent = withAuth(withFlow("first-step-finished")(SecondStep))

重要なことは、ステップフローを実行するときにredux状態を正しく更新することだけです。ユーザーが設定した最初のステップを完了すると

state.flow["first-step-finished"] = true // or however you manage your state

そのため、ユーザーが特定のページに手動で移動したときに、メモリ状態であり、redirectPathルートにリダイレクトされるため、ユーザーはそのredux状態になりません。

0
zhuber