2

I have this simple hybrid SPA build with Astro, React, and RRDv6
Route tree:

˫ localhost/ ------------------(public page)
˫ localhost/login ------------(admin login page)
˪ localhost/admin/home ---(admin dashboard page)

When I have successfully logged in and redirected to admin dashboard page, no error or any warning is present. I tried to refresh the page to simulate refreshing dashboard to fetch latest data from database through API. Instead I am having this error in my console log and my page is rendered blank.

Uncaught Error: useNavigate() may be used only in the context of a <Router> component.

Am I missing the RRDv6 concept, or missing something that is important?

env: node 16.13.0, npm 8.3.0
deps: @astrojs/react 2.0.2, astro 2.0.16, react 18.2.0, react-router-dom 6.11.1
script: dev = astro dev
cmd: npm run dev

Routes:

export default function Admin() {
  const [cookie, setCookie, removeCookie] = useCookies(['token']);

  const PrivateRoute = () => {
    const location = useLocation()

    const isAuthenticated = () => {
      return cookie.token !== null && cookie.token !== undefined;
    };

    return isAuthenticated()
      ? <Outlet />
      : <Navigate to="/admin" replace state={{ from: location }} />;
  };

  return (
    <BrowserRouter>
      <Routes>
        <Route path="/login" element={<AdminLogin />} />
        <Route path="/admin" element={<PrivateRoute />}>
          <Route path="home" element={<AdminHome />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}

Admin Dashboard:

export default function AdminHome() {
  const [cookie, setCookie, removeCookie] = useCookies(['token']);
  const [doLogout, setDoLogout] = useState(false)

  const navigate= useNavigate()

  useEffect(() => {
    if (doLogout) {
      removeCookie('token', { sameSite: 'none', secure: true })
      navigate('/login')
    }
  }, [doLogout])

  return (
    <div>
      <AdminAppbar cookie={cookie} logout={setDoLogout} />
      <AdminBlog/>
    </div>
  );
}
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
mitchiri_neko
  • 1,735
  • 2
  • 7
  • 12
  • 2
    Other than `PrivateRoute` being incorrectly declared inside another React component I don't see overt issues with this code. Can you [edit] the post to share how you are building and running/serving the app locally? – Drew Reese May 18 '23 at 04:09
  • I have edited the question and added my local settings – mitchiri_neko May 18 '23 at 10:45

1 Answers1

0

The only issues I see in the code are:

  • The PrivateRoute component is declared inside another React component. Each time the parent component renders, a new "instance" of PrivateRoute is created and that component's entire ReactTree is torn down and the new "instance" mounted. React components generally should be declared on their own.

  • The protected route is redirecting to itself when the isAuthenticated evaluates falsey. This is likely creating a render loop which is why the page is blank. Routes you are protecting should not redirect to other protected routes.

    Update PrivateRoute to redirect to the authentication route.

const PrivateRoute = () => {
  const location = useLocation();
  const [cookie, setCookie, removeCookie] = useCookies(['token']);

  const isAuthenticated = cookie.token !== null && cookie.token !== undefined;

  return isAuthenticated
    ? <Outlet />
    : (
      <Navigate
        to="/login" // <-- redirect to non-protected route
        replace
        state={{ from: location }}
      />
    );
};
export default function Admin() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/login" element={<AdminLogin />} />
        <Route path="/admin" element={<PrivateRoute />}>
          <Route path="home" element={<AdminHome />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
}
Drew Reese
  • 165,259
  • 14
  • 153
  • 181
  • This doesn't resolve the problem for me, I think it is due to the difference in nature of AstroJS and React handle routing. So I'll mark this as completed for now, in case in the future there is much better answer. – mitchiri_neko May 27 '23 at 05:49
  • @mitchiri_neko Hmm, ok, I'll take a look at what astro is to see if anything jumps out as needing to be set/configured/updated/etc. – Drew Reese May 27 '23 at 05:53