UPDATE
After changing PrivateRoute.js code to:
import React from 'react';
import {Navigate, Outlet} from 'react-router-dom';
const PrivateRoute = () => {
const isAuthenticated = localStorage.getItem("authToken");
return isAuthenticated ? <Outlet /> : <Navigate to="/login"/>
};
export default PrivateRoute;
The errors and warnings are gone but now it's just a blank screen
This is the first error
history.ts:491 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 (history.ts:491:1)
at Route (components.tsx:353:1)
at renderWithHooks (react-dom.development.js:16305:1)
at mountIndeterminateComponent (react-dom.development.js:20074:1)
at beginWork (react-dom.development.js:21587:1)
at HTMLUnknownElement.callCallback (react-dom.development.js:4164:1)
at Object.invokeGuardedCallbackDev (react-dom.development.js:4213:1)
at invokeGuardedCallback (react-dom.development.js:4277:1)
at beginWork$1 (react-dom.development.js:27451:1)
at performUnitOfWork (react-dom.development.js:26557:1)
This is the issue I get in my MERN Stack project in React but I am almost certain that the code is good, btw my Back-end works great
App.js
import {BrowserRouter as Router, Routes, Route} from 'react-router-dom'
//Routing
import PrivateRoute from './components/routing/PrivateRoute';
//Screens
import PrivateScreen from './components/screens/PrivateScreen'
import LoginScreen from './components/screens/LoginScreen'
import RegisterScreen from './components/screens/RegisterScreen'
import ForgotPasswordScreen from './components/screens/ForgotPasswordScreen'
import ResetPasswordScreen from './components/screens/ResetPasswordScreen'
const App = () => {
return (
<Router>
<div className="app">
<Routes>
<Route path="/" element={<PrivateRoute />}>
<Route element={<PrivateScreen />} />
</Route>
<Route path="/login" element={<LoginScreen />} />
<Route path="/register" element={<RegisterScreen />} />
<Route path="/forgotpassword" element={<ForgotPasswordScreen />} />
<Route path="/passwordreset/:resetToken" element={< ResetPasswordScreen />} />
</Routes>
</div>
</Router>
);
}
export default App;
PrivateRoute.js
import React from 'react';
import { Route, Navigate } from 'react-router-dom';
const PrivateRoute = ({ component: Component, ...rest }) => {
const isAuthenticated = localStorage.getItem("authToken");
if (isAuthenticated) {
return <Route {...rest} element={<Component />} />;
} else {
return <Navigate to="/login" />;
}
};
export default PrivateRoute;
Btw there is an warning in this script for line 8 that says
react-jsx-dev-runtime.development.js:87 Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check your code at PrivateRoute.js:8.
at PrivateRoute (http://localhost:3000/static/js/bundle.js:189:14)
at RenderedRoute (http://localhost:3000/static/js/bundle.js:40635:5)
at Routes (http://localhost:3000/static/js/bundle.js:41267:5)
at div
at Router (http://localhost:3000/static/js/bundle.js:41205:15)
at BrowserRouter (http://localhost:3000/static/js/bundle.js:39306:5)
at App
And I can't seem to figure out why
PrivateScreen.js
import {useState, useEffect} from "react";
import axios from 'axios';
import {useNavigate} from "react-router-dom";
const PrivateScreen = () =>{
const history = useNavigate();
const [error, setError] = useState("");
const [privateData, setPrivateData] = useState("");
useEffect(() => {
if(!localStorage.getItem("authToken")){
history("/login");
}
const fetchPrivateData = async () => {
const config = {
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${localStorage.getItem("authToken")}`
}
}
try {
const {data} = await axios.get("/api/private", config);
setPrivateData(data.data);
}catch (e) {
localStorage.removeItem("authToken");
setError("You are not authorized, please login");
}
}
fetchPrivateData().then().catch(error => {
console.log("Error:", error);
});
}, [history]);
const logoutHandler = () => {
localStorage.removeItem("authToken");
history("/login");
}
return error ? (
<span className="error-message">{error}</span>
) : (
<>
<div style={{background: "green", color:"white"}}>{privateData}</div>
<button onClick={logoutHandler} className="">Logout</button>
</>
);
};
export default PrivateScreen;
I went on many websites like StackOverflow and GitHub, I read the documentation for react-router-dom v6, I switched from history to useNavigate, I tried with AI assistents and a friend checked my code but nothing seemed to work
The code works only first time but when it redirects to PrivateScreen it just starts showing these errors