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...
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 />} />