0

I'm attempting to create a private route based on the answers here, however it is not performing the redirect.

This is my private route component

import React, { Component, useContext } from "react";
import { Redirect, Route, RouteComponentProps, RouteProps } from "react-router-dom";
import { RootStoreContext } from "../stores/rootStore";
import { observer } from "mobx-react-lite";

const PrivateRoute: React.FC<RouteProps> = ({ children, ...rest }) => {
    const rootStore = useContext(RootStoreContext);
    const { isAuthenticated } = rootStore.msalStore;

    return (
        <Route
            {...rest}
            render={(props: RouteComponentProps<{}>) =>
                isAuthenticated ? (
                    <Component {...props} />
                ) : (
                    <Redirect to={{ pathname: "/", state: { from: props.location } }} />
                )
            }
        />
    );
};

export default observer(PrivateRoute);

And this is my App.tsx

//Imports

const App: React.FC = () => {
    return (
        <>
            <BrowserRouter>
                <ThemeProvider theme={theme}>
                    <Route exact path="/" component={LoginPage} />
                    <Route path="/authcallback" component={AuthCallback} />
                    <PrivateRoute path="/home" component={HomePage} />
                </ThemeProvider>
            </BrowserRouter>
        </>
    );
};

export default App;

When I type /home in the browser, or create a test button that navigates to home, it loads the component even though isAuthenticated = false.

I know it's not related to the value of isAuthenticated in my mobx store as changing to const [isAuthenticated, setIsAuthenticated] = useState(false); doesn't work either. I also have no other instances of routing in my app.

What could be the issue here?

Konzy262
  • 1,819
  • 3
  • 23
  • 45

2 Answers2

1

use Switch (from react-router-dom) to wrap routes,

import { Switch } from "react-router-dom";

const App: React.FC = () => {
    return (
        <>
            <BrowserRouter>
                <ThemeProvider theme={theme}>
                   <Switch>
                    <Route exact path="/" component={LoginPage} />
                    <Route path="/authcallback" component={AuthCallback} />
                    <PrivateRoute path="/home" component={HomePage} />
                   </Switch>
                </ThemeProvider>
            </BrowserRouter>
        </>
    );
};

export default App;
Tina
  • 156
  • 1
  • 7
  • The switch didn't help but [this](https://stackoverflow.com/questions/47747754/how-to-rewrite-the-protected-private-route-using-typescript-and-react-router-4-a) did. I believe I was experiencing [this](https://stackoverflow.com/questions/57408430/warning-you-should-not-use-route-component-and-route-render-in-the-same-rou) problem. Thanks – Konzy262 Nov 02 '20 at 16:22
0

This discussion helped me

My solution...

https://codesandbox.io/s/modest-fire-6mj3i?file=/src/PrivateRoute.tsx:0-517

import * as React from "react";
import { BrowserRouter, Link, Route, Switch } from "react-router-dom";
import PrivateRoute from "./PrivateRoute";

import "./styles.css";

const Home: React.FC = () => {
  return <div>Home</div>;
};

const Login: React.FC = () => {
  return <div>Login</div>;
};

export default function App() {
  return (
    <BrowserRouter>
      <ul>
        <li>
          <Link to="/home">Home</Link>
        </li>
        <li>
          <Link to="/">Login</Link>
        </li>
      </ul>
      <Switch>
        <Route exact path="/" component={Login} />
        <PrivateRoute redirectPath="/login" path="/home" component={Home} />
      </Switch>
    </BrowserRouter>
  );
}
import { Redirect, Route, RouteProps } from "react-router";
import React, { useState } from "react";

export interface IPrivateRouteProps extends RouteProps {
  redirectPath: string;
}

const PrivateRoute: React.FC<IPrivateRouteProps> = (props) => {
  const [isAuthenticated, setIsAuthenticated] = useState(false);

  return isAuthenticated ? (
    <Route {...props} component={props.component} render={undefined} />
  ) : (
    <Redirect to={{ pathname: props.redirectPath }} />
  );
};

export default PrivateRoute;

If I click Home I get redirected to /login and the Home component is hidden

useState is only used for testing the authenticated state from within the component.

Konzy262
  • 1,819
  • 3
  • 23
  • 45