157

認証済みルートを実装しようとしていましたが、React Router 4 がこれを妨げていることがわかりました。

<Route exact path="/" component={Index} />
<Route path="/auth" component={UnauthenticatedWrapper}>
    <Route path="/auth/login" component={LoginBotBot} />
</Route>
<Route path="/domains" component={AuthenticatedWrapper}>
    <Route exact path="/domains" component={DomainsIndex} />
</Route>

エラーは次のとおりです。

警告:同じルートで<Route component>andを使用しないでください。無視されます<Route children><Route children>

その場合、これを実装する正しい方法は何ですか?

react-router(v4)ドキュメントに表示され、次のようなことを示唆しています

<Router>
    <div>
    <AuthButton/>
    <ul>
        <li><Link to="/public">Public Page</Link></li>
        <li><Link to="/protected">Protected Page</Link></li>
    </ul>
    <Route path="/public" component={Public}/>
    <Route path="/login" component={Login}/>
    <PrivateRoute path="/protected" component={Protected}/>
    </div>
</Router>

しかし、たくさんのルートをグループ化しながらこれを達成することは可能ですか?


いくつかの調査の後、私はこれを思いつきました:

import React, {PropTypes} from "react"
import {Route} from "react-router-dom"

export default class AuthenticatedRoute extends React.Component {
  render() {
    if (!this.props.isLoggedIn) {
      this.props.redirectToLogin()
      return null
    }
    return <Route {...this.props} />
  }
}

AuthenticatedRoute.propTypes = {
  isLoggedIn: PropTypes.bool.isRequired,
  component: PropTypes.element,
  redirectToLogin: PropTypes.func.isRequired
}

でアクションをディスパッチするのは正しいrender()ですか? それは間違っていると感じます。componentDidMountまたは他のフックでも、実際には正しくないようです。

4

19 に答える 19

4

react-router-dom をインストールします

次に、有効なユーザー用と無効なユーザー用の 2 つのコンポーネントを作成します。

app.jsでこれを試してください

import React from 'react';

import {
BrowserRouter as Router,
Route,
Link,
Switch,
Redirect
} from 'react-router-dom';

import ValidUser from "./pages/validUser/validUser";
import InValidUser from "./pages/invalidUser/invalidUser";
const loggedin = false;

class App extends React.Component {
 render() {
    return ( 
      <Router>
      <div>
        <Route exact path="/" render={() =>(
          loggedin ? ( <Route  component={ValidUser} />)
          : (<Route component={InValidUser} />)
        )} />

        </div>
      </Router>
    )
  }
}
export default App;
于 2017-06-07T08:52:18.523 に答える
1

私の以前の答えはスケーラブルではありません。これが私が良いアプローチだと思うものです-

あなたのルート-

<Switch>
  <Route
    exact path="/"
    component={matchStateToProps(InitialAppState, {
      routeOpen: true // no auth is needed to access this route
    })} />
  <Route
    exact path="/profile"
    component={matchStateToProps(Profile, {
      routeOpen: false // can set it false or just omit this key
    })} />
  <Route
    exact path="/login"
    component={matchStateToProps(Login, {
      routeOpen: true
    })} />
  <Route
    exact path="/forgot-password"
    component={matchStateToProps(ForgotPassword, {
      routeOpen: true
    })} />
  <Route
    exact path="/dashboard"
    component={matchStateToProps(DashBoard)} />
</Switch>

アイデアは、component認証が必要ない場合は元のコンポーネントを返すか、すでに認証されている場合はログインなどのデフォルトのコンポーネントを返す小道具でラッパーを使用することです。

const matchStateToProps = function(Component, defaultProps) {
  return (props) => {
    let authRequired = true;

    if (defaultProps && defaultProps.routeOpen) {
      authRequired = false;
    }

    if (authRequired) {
      // check if loginState key exists in localStorage (Your auth logic goes here)
      if (window.localStorage.getItem(STORAGE_KEYS.LOGIN_STATE)) {
        return <Component { ...defaultProps } />; // authenticated, good to go
      } else {
        return <InitialAppState { ...defaultProps } />; // not authenticated
      }
    }
    return <Component { ...defaultProps } />; // no auth is required
  };
};
于 2019-01-24T17:53:16.963 に答える
0

ここに私自身のアプローチがあります

const RedirectionUnit = () => {
  const [user] = useContext(AuthContext);
  const pathname = useLocation().pathname;
  let redirectTo;
  if (user === null) redirectTo = "login";
  else if (pathname === "/")
    if (user.type === "supervisor"      ) redirectTo = "all-parteners";
    else if (user.type === "manager"    ) redirectTo = "all-employees";
    else if (user.type === "employee"   ) redirectTo = "unfinished-tasks";
  if (redirectTo && '/' + redirectTo !== pathname)
    return <Redirect to={redirectTo} />;
  return null;
};

const NavigationRoutes = () => {
  return (
    <>
      <Route component={RedirectionUnit} />
      {/* prettier-ignore */}
      <Switch>
        <Route exact path="/login"            component={Login} />
        <Route exact path="/logout"           component={Logout} />
        <Route exact path="/new-parteners"    component={NewParteners} />
        <Route exact path="/all-parteners"    component={AllParteners} />
        <Route exact path="/new-employees"    component={NewEmployees} />
        <Route exact path="/all-employees"    component={AllEmployees} />
        <Route exact path="/unfinished-tasks" component={UnfinishedTasks} />
        <Route exact path="/finished-tasks"   component={FinishedTasks} />
        <Route exact path="/finished-tasks"   component={FinishedTasks} />
        <Route component={NotFound} />
      </Switch>
    </>
  );
};
于 2021-08-22T21:50:28.733 に答える