Here is the code I am working with:
App.js
import NotFound from "components/NotFound";
import Loading from "components/Loading";
import PrivateRoute from "components/PrivateRoute";
import { logoutUser, setCurrentUser } from "features/auth/auth.slice";
import jwt_decode from "jwt-decode";
import React, { lazy, Suspense, useEffect } from "react";
import { useDispatch } from "react-redux";
import { Route, Switch, Redirect, useHistory } from "react-router-dom";
import HomeNav from "components/HomeNav";
// auth
const Login = lazy(() => import("features/auth/Login"));
const Register = lazy(() => import("features/auth/Register"));
const ForgotPassword = lazy(() => import("features/auth/ForgotPassword"));
const ResetPassword = lazy(() => import("features/auth/ResetPassword"));
// recipe
const Home = lazy(() => import("features/recipes/Home"));
const MyLikes = lazy(() => import("features/recipes/MyLikes"));
const MyRecipes = lazy(() => import("features/recipes/MyRecipes"));
const CreateRecipe = lazy(() => import("features/recipes/CreateRecipe"));
const EditRecipe = lazy(() => import("features/recipes/EditRecipe"));
const RecipeDetail = lazy(() => import("features/recipes/RecipeDetail"));
const UserProfile = lazy(() => import("features/recipes/UserProfile"));
const TopRecipes = lazy(() => import("features/recipes/TopRecipes"));
// user
const MyProfile = lazy(() => import("features/user/MyProfile"));
const App = () => {
const history = useHistory();
const dispatch = useDispatch();
// Check if user is already logged in
useEffect(() => {
const token = localStorage.token;
// Check for token to keep user logged in
if (token) {
try {
// Decode token and get user info and exp
const { exp, ...rest } = jwt_decode(token);
// Set user and isAuthenticated
dispatch(setCurrentUser(rest));
// Check for expired token
const currentTime = Date.now() / 1000; // to get in milliseconds
if (exp < currentTime) {
// Logout user
dispatch(logoutUser());
// Redirect to login
history.push("/");
}
} catch {
// Logout user
dispatch(logoutUser());
// Redirect to login
history.push("/");
}
}
}, []);
const authRoutes = [
{
path: "/",
Component: Login,
},
{
path: "/register",
Component: Register,
},
{
path: "/forgotpassword",
Component: ForgotPassword,
},
{
path: "/resetpassword/:resetToken",
Component: ResetPassword,
},
];
const privateRoutes = [
{
path: "/home",
Component: Home,
},
{
path: "/top-3",
Component: TopRecipes,
},
{
path: "/my-likes",
Component: MyLikes,
},
{
path: "/my-recipes",
Component: MyRecipes,
},
{
path: "/profile",
Component: MyProfile,
},
{
path: "/create",
Component: CreateRecipe,
},
{
path: "/recipe/:recipeId",
Component: RecipeDetail,
},
{
path: "/update/:recipeId",
Component: EditRecipe,
},
{
path: "/profile/:username",
Component: UserProfile,
},
];
return (
<Suspense fallback={<Loading />}>
<Switch>
{/* auth routes */}
{authRoutes.map(({ path, Component }, i) => (
<Route exact path={path} component={Component} key={i} />
))}
{/* private routes */}
{privateRoutes.map(({ path, Component }, i) => (
<PrivateRoute exact path={path} Component={Component} key={i} />
))}
{/* not found */}
<Route path="/404" component={NotFound} />
<Redirect to="/404" />
</Switch>
</Suspense>
);
};
export default App;
PrivateRoute.js
import React from "react";
import { Route, Redirect, useLocation } from "react-router-dom";
import { useSelector } from "react-redux";
import HomeNav from "components/HomeNav";
const PrivateRoute = ({ Component, ...rest }) => {
const isAuthenticated = useSelector((state) => state.auth.isAuthenticated);
const { pathname } = useLocation();
return (
<Route
{...rest}
render={(props) =>
isAuthenticated ? (
<HomeNav>
<Component {...props} />
</HomeNav>
) : (
<Redirect to={{ pathname: "/", from: pathname }} />
)
}
/>
);
};
export default PrivateRoute;
This is the result I was looking for in that it renders the HomeNav component as a parent on all protected routes, but it causes a rerender each time a new link is visited. In addition, if I just wrap the PrivateRoutes inside of App.js in a HomeNav, it also works, but does not properly show the Not Found page. Any help would be appreciated!