登录页面无法使用React Router ProtectedRoute呈现

时间:2019-03-15 15:22:48

标签: reactjs authentication react-router router

我有一个反应路由器应用程序:

    export default () => (
  <Router basename={process.env.REACT_APP_BASENAME || ""}>
    <div>
      {routes.map((route, index) => {
        return (
          <PrivateRoute
            key={index}
            path={route.path}
            exact={route.exact}
            component={props => {
              return (
                <route.layout {...props}>
                  <route.component {...props} />
                </route.layout>
              );
            }}
          />
        );
      })}
    </div>
  </Router>
);

,这将根据所单击的路线呈现不同的视图。路线将基于此对象在routes.js文件中呈现:

    export default [
        {
    path: "/login",
    layout: DefaultLayout,
    component: LogIn
  },    .....]

要构建某种身份验证,我将PrivateRoute定义为:

    const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route {...rest} render={(props) => (
    fakeAuth.isAuthenticated === true
      ? <Component {...props} />
      : <Redirect to='/login' />
  )} />
)

但是,当我将应用程序设置为使用PrivateRoute而不是常规Route(在第一个代码段中)时,重定向不使用路由对象。如何更改登录页面的PrivateRoute常量以反映我的原始React Route体系结构?最佳做法是什么?

2 个答案:

答案 0 :(得分:0)

您的代码看起来不错,但是由于您说routes对象不能被react-router理解,因此可能存在组件定义不正确的情况。例如,可以在创建对象后 定义您的组件。在这种情况下,创建该对象时,它将引用undefined组件。我曾经犯过一次这个错误,所以我只是在分享可能出了什么问题。

这里是一个例子:

import ReactDOM from "react-dom";
import React, { Component } from "react";
import {
  BrowserRouter as Router,
  Route,
  Link,
  Redirect,
  withRouter
} from "react-router-dom";

function Public() {
  return <h3>Public</h3>;
}

function Protected() {
  return <h3>You can see protected content</h3>;
}

class Login extends Component {
  state = { redirectToReferrer: false };

  login = () => {
    fakeAuth.authenticate(() => {
      this.setState({ redirectToReferrer: true });
    });
  };

  render() {
    let { from } = this.props.location.state || { from: { pathname: "/" } };
    let { redirectToReferrer } = this.state;

    if (redirectToReferrer) return <Redirect to={from} />;

    return (
      <div>
        <p>You must log in to view the page at {from.pathname}</p>
        <button onClick={this.login}>Log in</button>
      </div>
    );
  }
}

const routes = [
  {
    path: "/public",
    component: Public,
    private: false
  },
  {
    path: "/login",
    component: Login,
    private: false
  },
  {
    path: "/protected",
    component: Protected,
    private: true
  }
];

function AuthExample() {
  return (
    <Router>
      <div>
        <AuthButton />
        <ul>
          <li>
            <Link to="/public">Public Page</Link>
          </li>
          <li>
            <Link to="/protected">Protected Page</Link>
          </li>
        </ul>
        {routes.map((route, index) => {
          if (route.private)
            return (
              <PrivateRoute
                key={index}
                path={route.path}
                exact={route.exact}
                component={props => {
                  return <route.component {...props} />;
                }}
              />
            );

          return (
            <Route
              key={index}
              path={route.path}
              exact={route.exact}
              component={props => {
                return <route.component {...props} />;
              }}
            />
          );
        })}
      </div>
    </Router>
  );
}

const fakeAuth = {
  isAuthenticated: false,
  authenticate(cb) {
    this.isAuthenticated = true;
    setTimeout(cb, 100); // fake async
  },
  signout(cb) {
    this.isAuthenticated = false;
    setTimeout(cb, 100);
  }
};

const AuthButton = withRouter(({ history }) =>
  fakeAuth.isAuthenticated ? (
    <p>
      Welcome!{" "}
      <button
        onClick={() => {
          fakeAuth.signout(() => history.push("/"));
        }}
      >
        Sign out
      </button>
    </p>
  ) : (
    <p>You are not logged in.</p>
  )
);

function PrivateRoute(props) {
  const { component: Component, ...rest } = props;
  return (
    <Route
      {...rest}
      render={props =>
        fakeAuth.isAuthenticated ? (
          <Component {...props} />
        ) : (
          <Redirect
            to={{
              pathname: "/login",
              state: { from: props.location }
            }}
          />
        )
      }
    />
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<AuthExample />, rootElement);

通知PublicProtectedLogin组件是在routes对象上方定义的。在routes之后定义它们会导致错误。

答案 1 :(得分:0)

我建议按照以下方式更改您的私人路线

const PrivateRoute = ({ component: Component, ...rest }) => fakeAuth.isAuthenticated === true ? (
  <Route {...rest} component={component}
  )} />
) : <Redirect to='/login' />;