So I've been upgrading modules for a project that is not mine so I'm not familiar with the code, when I tried upgrading react-router-dom from 5.2.0 ❯ 6.3.0 I stumbled with the way the routes are implemented. Having replaced the reprecated modules I get multiple errors that basically say the routes are not being defined correctly but I tried everything and I can't get it to work. These are the errors I get when I load the page.
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
Matched leaf route at location "/" does not have an element. This means it will render an <Outlet /> with a null value by default resulting in an "empty" page.
Uncaught Error: [Navigate] is not a <Route> component. All component children of <Routes> must be a <Route> or <React.Fragment>
This is the app component that deals with the routes.
import routes from './App.routes'
import { lazy } from 'react'
import AppContainer from './containers/app'
import AuthContainer from './containers/auth'
import { Route, Routes, Navigate, useNavigate, useRoutes } from 'react-router-dom'
import { ModalError } from './components/ModalError/ModalError'
import { EnvironmentProvider } from './contexts/Environment'
import { useDispatch, useSelector } from 'react-redux'
import { hiddenError } from './store/slices/health'
import { FullScreenLoading } from './components/FullScreenLoading/FullScreenLoading'
import { Suspense, useEffect, useState } from 'react'
import * as actionsProfile from './store/slices/profile'
import { firebaseInit, getValuesRemoteConfig } from './service/firebase'
import { setSecret } from './service/cryptojs'
import axios from './config/axios'
import Maintenance from './pages/common/maintenance/maintenance'
import { googleAnalyticsRegisterView } from './components/GoogleAnalytics/GoogleAnalytics'
const App = () => {
const [isLoadingConfig, setIsLoadingConfig] = useState(true)
const [configBeSetted, setConfigBeSetted] = useState(false)
const [appInitialized, setAppInitialized] = useState(false)
const [configuration, setConfiguration] = useState({
isMaintenanceWebMessage: null,
isMaintenanceWeb: null,
apiUrlRemote: null,
timeoutRemote: null,
secretRemote: null,
publicWebUrl: null,
publicTurnsUrl: null,
successRedirectUri: null,
errorRedirectUri: null,
googlePlayUrl: null,
appStoreUrl: null,
})
const token = JSON.parse(localStorage.getItem('tsu'))?.token
const { showError } = useSelector((state) => state.health.health)
const dispatch = useDispatch()
useEffect(() => {
firebaseInit(async (app) => {
const config = await getValuesRemoteConfig(app)
//Production
axios.defaults.baseURL = config.apiUrlRemote
axios.defaults.timeout = config.timeoutRemote
setSecret(config.secretRemote)
setConfiguration(config)
setIsLoadingConfig(false)
setConfigBeSetted(true)
setAppInitialized(true)
token && dispatch(actionsProfile.getProfileData())
})
}, [token])
if (isLoadingConfig || !configBeSetted) return <FullScreenLoading />
if (configBeSetted && configuration?.isMaintenanceWeb) {
return (
<EnvironmentProvider config={configuration}>
<Maintenance message={configuration?.isMaintenanceWebMessage} />
</EnvironmentProvider>
)
}
return (
<Suspense fallback={<FullScreenLoading />}>
<EnvironmentProvider config={configuration}>
{showError && <ModalError onClose={() => dispatch(hiddenError())} />}
<Routes>
{routes
.map((route) => ({
...route,
component: appInitialized
? googleAnalyticsRegisterView(route.component)
: route.component,
}))
.map((route, i) => {
const Container = route.private ? AppContainer : AuthContainer
return (
<Route
key={i}
path={route.path}
exact={route.exact}
render={(props) => {
return (
<Container key={i}>
<route.component {...props} />
</Container>
)
}}
/>
)
})}
<Navigate to={token ? '/home' : '/'} />
</Routes>
</EnvironmentProvider>
</Suspense>
)
}
export default App
This is the routes component.
import { lazy } from 'react'
import { googleAnalyticsRegisterView } from './components/GoogleAnalytics/GoogleAnalytics'
const Home = lazy(() => import('./pages/app/home'))
const MyData = lazy(() => import('./pages/app/my-data'))
const ClientAttention = lazy(() => import('./pages/app/client-atention'))
const PhoneAssistance = lazy(() => import('./pages/app/phone-assitance'))
const InsuranceDetails = lazy(() => import('./pages/app/insurance-details'))
const FeePayment = lazy(() => import('./pages/app/fee-payment'))
const MyInsurance = lazy(() => import('./pages/app/my-insurance'))
const ReportClaim = lazy(() => import('./pages/app/report-claim'))
const Notifications = lazy(() => import('./pages/app/notifications'))
const Login = lazy(() => import('./pages/auth/login'))
const RecoverPassword = lazy(() => import('./pages/auth/recover-password'))
const Register = lazy(() => import('./pages/auth/register'))
const NewPassword = lazy(() => import('./pages/auth/new-password'))
const FrecuentlyQuestions = lazy(() =>
import('./pages/app/frecuently-question')
)
const ProofOfPayment = lazy(() =>
import('./pages/common/proof-of-payment/ProofOfPayment')
)
const SuccessPayment = lazy(() =>
import('./pages/common/payments/success/SuccessPayment')
)
const ErrorPayment = lazy(() =>
import('./pages/common/payments/error/ErrorPayment')
)
const AppRedirect = lazy(() => import('./pages/auth/app-redirect'))
export const privateRoutes = [
'/home',
'/my-data',
'/phone-assistance',
'/client-attention',
'/details',
'/fee-payment',
'/my-insurances',
'/report-claim',
'/notifications',
'/faqs',
]
export const publicRoutes = [
'/',
'/recover-password',
'/new-password',
'/register',
'/certifacates',
'/app-redirect',
]
const routes = [
{
component: SuccessPayment,
path: '/success-payment',
exact: true,
private: !!localStorage.getItem('tsu'),
},
{
component: ErrorPayment,
path: '/error-payment',
exact: true,
private: !!localStorage.getItem('tsu'),
},
{
component: Login,
path: '/',
exact: true,
private: false,
},
{
component: RecoverPassword,
path: '/recover-password',
exact: true,
private: false,
},
{
component: NewPassword,
path: '/new-password',
exact: true,
private: false,
},
{
component: Register,
path: '/register',
exact: true,
private: false,
},
{
component: Home,
path: '/home',
exact: true,
private: true,
},
{
component: MyData,
path: '/my-data',
exact: true,
private: true,
},
{
component: PhoneAssistance,
path: '/phone-assistance',
exact: true,
private: true,
},
{
component: ClientAttention,
path: '/client-attention',
exact: true,
private: true,
}
]
export default routes
And this is the main component where app is rendered
import React from 'react'
import { createRoot } from 'react-dom/client'
import App from './App'
import GlobalStyles from './global-styles'
import ErrorBoundary from './components/ErrorBoundary/ErrorBoundary'
import store, { history } from './store'
import { HashRouter } from 'react-router-dom'
import { Provider } from 'react-redux'
import * as Sentry from '@sentry/react'
import { BrowserTracing } from '@sentry/tracing'
Sentry.init({
dsn: import.meta.env.VITE_SENTRY_KEY,
integrations: [new BrowserTracing()],
tracesSampleRate: 1.0,
})
const container = document.getElementById('root')
const root = createRoot(container) // createRoot(container!) if you use TypeScript
root.render(
<React.StrictMode>
<ErrorBoundary>
<Provider store={store}>
<HashRouter ref={history}>
<GlobalStyles />
<App />
</HashRouter>
</Provider>
</ErrorBoundary>
</React.StrictMode>
)
History is exported like export const history = createRef();
I know there is something about that ref property or HashRouter but in the documentation I can't find it.