I want to use React Router for my website, but I’m doing something wrong.
The routes that I defined are:
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<SecuredApp>
<Router>
<Routes>
<Route path='/login' element={<Login/>}/>
<Route element={<SecuredRoute />}>
<Route path='/home' element={<Home/>}/>
<Route path='/perfil' element={<Profile/>}/>
</Route>
<Route path='/' element={<Navigate exact from='/' to='/home' />}/>
</Routes>
</Router>
</SecuredApp>
</React.StrictMode>,
document.getElementById('root')
);
At college, I’ve been taught to use something as SecuredApp and SecuredRoute so, when a user tries to enter at /home (for example) without login, it will redirect him to /login.
I defined those like this:
import {Navigate, Route} from 'react-router-dom'
import API from '../../api'
const AuthenticationContext = React.createContext({
isAuthenticated: false,
errors: false,
login: () => {},
logout: () => {},
reset: () => {}
})
const client = API.instance()
// eslint-disable-next-line react/prop-types
function SecuredApp({children}) {
const [isAuthenticated, setIsAuthenticated] = useState(JSON.parse(localStorage.getItem('authenticated') || false))
const [errors, setErrors] = useState(false)
const reset = async () => {
localStorage.setItem('authenticated', JSON.stringify(false))
setErrors(false)
setIsAuthenticated(false)
}
const login = async (user, pass) => {
const loginSuccessful = await client.login(user, pass)
localStorage.setItem('authenticated', JSON.stringify(loginSuccessful))
setIsAuthenticated(loginSuccessful)
setErrors(!loginSuccessful)
}
const logout = async () => {
await client.logout()
await reset()
}
const context = { isAuthenticated, login, logout, errors, reset }
return <AuthenticationContext.Provider value = { context } >
{ children }
</AuthenticationContext.Provider>
}
// eslint-disable-next-line react/prop-types
function SecuredRoute({children, ...props}) {
const {isAuthenticated} = useContext(AuthenticationContext)
return isAuthenticated ? <Route {...props}>{children}</Route> : <Navigate to = '/login' />
}
export { AuthenticationContext, SecuredApp, SecuredRoute }
It succeeds to redirect to login when the user hasn’t authenticated but, when I log in, I encounter this problem:
at invariant (react-router-dom.js?v=ef4966f0:209:11)
at Route (react-router-dom.js?v=ef4966f0:3934:10)
at renderWithHooks (chunk-YYQEUSG3.js?v=ef4966f0:12171:26)
at mountIndeterminateComponent (chunk-YYQEUSG3.js?v=ef4966f0:14921:21)
at beginWork (chunk-YYQEUSG3.js?v=ef4966f0:15902:22)
at HTMLUnknownElement.callCallback2 (chunk-YYQEUSG3.js?v=ef4966f0:3674:22)
at Object.invokeGuardedCallbackDev (chunk-YYQEUSG3.js?v=ef4966f0:3699:24)
at invokeGuardedCallback (chunk-YYQEUSG3.js?v=ef4966f0:3733:39)
at beginWork$1 (chunk-YYQEUSG3.js?v=ef4966f0:19761:15)
at performUnitOfWork (chunk-YYQEUSG3.js?v=ef4966f0:19194:20)
react-router-dom.js?v=ef4966f0:209 Uncaught Error: A <Route> is only ever to be used as the child of <Routes> element, never rendered directly. Please wrap your <Route> in a <Routes>.
at invariant (react-router-dom.js?v=ef4966f0:209:11)
at Route (react-router-dom.js?v=ef4966f0:3934:10)
at renderWithHooks (chunk-YYQEUSG3.js?v=ef4966f0:12171:26)
at mountIndeterminateComponent (chunk-YYQEUSG3.js?v=ef4966f0:14921:21)
at beginWork (chunk-YYQEUSG3.js?v=ef4966f0:15902:22)
at HTMLUnknownElement.callCallback2 (chunk-YYQEUSG3.js?v=ef4966f0:3674:22)
at Object.invokeGuardedCallbackDev (chunk-YYQEUSG3.js?v=ef4966f0:3699:24)
at invokeGuardedCallback (chunk-YYQEUSG3.js?v=ef4966f0:3733:39)
at beginWork$1 (chunk-YYQEUSG3.js?v=ef4966f0:19761:15)
at performUnitOfWork (chunk-YYQEUSG3.js?v=ef4966f0:19194:20)
chunk-YYQEUSG3.js?v=ef4966f0:14036 The above error occurred in the <Route> component:
at Route (http://localhost:5173/node_modules/.vite/deps/react-router-dom.js?v=ef4966f0:3934:10)
at SecuredRoute (http://localhost:5173/src/context/auth/index.jsx?t=1715532288323:61:25)
at RenderedRoute (http://localhost:5173/node_modules/.vite/deps/react-router-dom.js?v=ef4966f0:3560:5)
at Routes (http://localhost:5173/node_modules/.vite/deps/react-router-dom.js?v=ef4966f0:3995:5)
at Router (http://localhost:5173/node_modules/.vite/deps/react-router-dom.js?v=ef4966f0:3938:15)
at BrowserRouter (http://localhost:5173/node_modules/.vite/deps/react-router-dom.js?v=ef4966f0:4678:5)
at SecuredApp (http://localhost:5173/src/context/auth/index.jsx?t=1715532288323:23:23)
Consider adding an error boundary to your tree to customize error handling behavior.
Visit https://reactjs.org/link/error-boundaries to learn more about error boundaries.
chunk-YYQEUSG3.js?v=ef4966f0:19409 Uncaught Error: A <Route> is only ever to be used as the child of <Routes> element, never rendered directly. Please wrap your <Route> in a <Routes>.
at invariant (react-router-dom.js?v=ef4966f0:209:11)
at Route (react-router-dom.js?v=ef4966f0:3934:10)
at renderWithHooks (chunk-YYQEUSG3.js?v=ef4966f0:12171:26)
at mountIndeterminateComponent (chunk-YYQEUSG3.js?v=ef4966f0:14921:21)
at beginWork (chunk-YYQEUSG3.js?v=ef4966f0:15902:22)
at beginWork$1 (chunk-YYQEUSG3.js?v=ef4966f0:19749:22)
at performUnitOfWork (chunk-YYQEUSG3.js?v=ef4966f0:19194:20)
at workLoopSync (chunk-YYQEUSG3.js?v=ef4966f0:19133:13)
at renderRootSync (chunk-YYQEUSG3.js?v=ef4966f0:19112:15)
at recoverFromConcurrentError (chunk-YYQEUSG3.js?v=ef4966f0:18732:28)
Thank you in advance, I hope someone can help me spot my mistake