0

I've had my own template code I have used through projects. I saw react-router-dom has made some changes to the key uses in particular with Switch-to-Routes and Redirect-to-Navigate. This seems to have broke the project and gives the following error...

enter image description here

First, I will show the old code that was working perfectly fine.

Second, I will show the code I have updated to match the v6 library names and updated suggestions I have found.

Here is the old(working) code

App.tsx

import React from 'react';
import {BrowserRouter as Router} from 'react-router-dom';
import './App.css';

// auth
import Routes from 'src/auth/Routes';

function App() {
  return (
    <div className='App'>
      <Router basename={process.env.REACT_APP_PUBLIC_URL}>
        <Routes />
      </Router>
    </div>
  );
}

export default App;

Routes.tsx

import React from 'react';
import {Switch} from 'react-router-dom';

// authentication
import {GuestRoute, UserRoute, GuestOrUserRoute} from 'src/auth/ProtectedRoutes';

// components
import Dashboard from 'src/views/Dashboard';
import Login from 'src/views/Login';

// utils
import {FRONTEND_LINKS} from 'src/utils';

function Routes() {
  return (
    <Switch>
      <GuestOrUserRoute exact path={FRONTEND_LINKS.dashboard} component={Dashboard} />
      <GuestRoute exact path={FRONTEND_LINKS.login} component={Login} />
    </Switch>
  );
}

export default Routes;

ProtectedRoutes.tsx

import React from 'react';
import {Route, Redirect} from 'react-router-dom';
import {useSelector, useDispatch} from 'react-redux';
import {bindActionCreators} from 'redux';

// components
import PageSpinner from 'src/components/spinners/BrowserSpinner';

// interfaces
import {IloadingState} from 'src/typeScriptInterfaces';

// utils
import {FRONTEND_LINKS} from 'src/utils';

// globals
import * as actionCreators from 'src/reduxStore/actions/actionCreators';

export function GuestRoute({component, ...rest}: any) {
  const dispatch = useDispatch();
  const {isLoggedIn} = bindActionCreators(actionCreators, dispatch);
  const loadingState: IloadingState = useSelector((state: any) => state.loading);
  const renderFn = (Component: any) => (props: any) => {
    if (loadingState.global) {
      return <PageSpinner />;
    } else if (isLoggedIn()) {
      return <Redirect to={FRONTEND_LINKS.dashboard} />;
    }
    return <Component {...props} />;
  };
  return <Route {...rest} render={renderFn(component)} />;
}

export function UserRoute({component, ...rest}: any) {
  const dispatch = useDispatch();
  const {isLoggedIn} = bindActionCreators(actionCreators, dispatch);
  const loadingState: IloadingState = useSelector((state: any) => state.loading);
  const renderFn = (Component: any) => (props: any) => {
    if (loadingState.global) {
      return <PageSpinner />;
    } else if (!isLoggedIn()) {
      return <Redirect to={FRONTEND_LINKS.login} />;
    }
    return <Component {...props} />;
  };
  return <Route {...rest} render={renderFn(component)} />;
}

export function GuestOrUserRoute({component, ...rest}: any) {
  const loadingState: IloadingState = useSelector((state: any) => state.loading);
  const renderFn = (Component: any) => (props: any) => {
    if (loadingState.global) {
      return <PageSpinner />;
    }
    return <Component {...props} />;
  };
  return <Route {...rest} render={renderFn(component)} />;
}

Here is the new(not working) code

App.tsx

import React from 'react';
import {BrowserRouter as Router} from 'react-router-dom';
import './App.css';

// auth
import SwitchRoutes from 'src/auth/SwitchRoutes';

function App() {
  return (
    <div className='App'>
      <Router basename={process.env.REACT_APP_PUBLIC_URL}>
        <SwitchRoutes />
      </Router>
    </div>
  );
}

export default App;

Routes.tsx

import React from 'react';
import {Routes} from 'react-router-dom';

// authentication
import {GuestRoute, UserRoute, GuestOrUserRoute} from 'src/auth/ProtectedRoutes';

// components
import Dashboard from 'src/views/Dashboard';
import Login from 'src/views/Login';

// utils
import {FRONTEND_LINKS} from 'src/utils';

function SwitchRoutes() {
  return (
    <Routes>
      <GuestOrUserRoute path={FRONTEND_LINKS.dashboard} element={<Dashboard />} />
      <GuestRoute path={FRONTEND_LINKS.login} element={<Login />} />
    </Routes>
  );
}

export default SwitchRoutes;

ProtectedRoutes.tsx

import React from 'react';
import {Route, Navigate} from 'react-router-dom';
import {useSelector, useDispatch} from 'react-redux';
import {bindActionCreators} from 'redux';

// components
import PageSpinner from 'src/components/spinners/BrowserSpinner';

// interfaces
import {IloadingState} from 'src/typeScriptInterfaces';

// utils
import {FRONTEND_LINKS} from 'src/utils';

// globals
import * as actionCreators from 'src/reduxStore/actions/actionCreators';

export function GuestRoute({component, ...rest}: any) {
  const dispatch = useDispatch();
  const {isLoggedIn} = bindActionCreators(actionCreators, dispatch);
  const loadingState: IloadingState = useSelector((state: any) => state.loading);
  const renderFn = (Component: any) => (props: any) => {
    if (loadingState.global) {
      return <PageSpinner />;
    } else if (isLoggedIn()) {
      return <Navigate to={FRONTEND_LINKS.dashboard} />;
    }
    return <Component {...props} />;
  };
  return <Route {...rest} render={renderFn(component)} />;
}

export function UserRoute({component, ...rest}: any) {
  const dispatch = useDispatch();
  const {isLoggedIn} = bindActionCreators(actionCreators, dispatch);
  const loadingState: IloadingState = useSelector((state: any) => state.loading);
  const renderFn = (Component: any) => (props: any) => {
    if (loadingState.global) {
      return <PageSpinner />;
    } else if (!isLoggedIn()) {
      return <Navigate to={FRONTEND_LINKS.login} />;
    }
    return <Component {...props} />;
  };
  return <Route {...rest} render={renderFn(component)} />;
}

export function GuestOrUserRoute({component, ...rest}: any) {
  const loadingState: IloadingState = useSelector((state: any) => state.loading);
  const renderFn = (Component: any) => (props: any) => {
    if (loadingState.global) {
      return <PageSpinner />;
    }
    return <Component {...props} />;
  };
  return <Route {...rest} render={renderFn(component)} />;
}

Any suggestions on what broke where would be very helpful? Thanks.

Edit:

please do not close this question, it is not the same as Error: [PrivateRoute] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>.

The difference is I am trying to use an wrapper for Route, and in the solution it is trying to pass any privateRoute as a component route, which would force dnry(do not repeat yourself) in my PrivateRoutes. That was the whole reason for the Route wrapper...

Wrapper - <GuestOrUserRoute path={FRONTEND_LINKS.dashboard} component={Dashboard} />

Suggested PrivateRoute passed as element - <Route path={FRONTEND_LINKS.dashboard} component={<GuestOrUserRoute />} />

Fiddle Freak
  • 1,566
  • 2
  • 29
  • 68
  • I guess I'll just go back to version 5, until someone wants to take the time to answer how to handle the changes breaking the wrapper... – Fiddle Freak Apr 28 '22 at 19:48

0 Answers0