How can i achieve a similar result just like Navigate
component of react-router has, in Nextjs?
There is a next/Router option but i want to return something to navigate.
i want to redirect the page, but not with router.push
because i have to use a useEffect
but i only want to know if there is a way to do the exact same thing using returning a component
Basically what is the equivalent of this in Nextjs without react-router
import { Navigate } from "react-router";
const Page = () => {
const { user } = useAuth();
if (user?.role.name === "user") {
return <Navigate to={"/app"} />;
} else {
return <Navigate to={"/app/workspaces"} />;
}
}
export default Page
(New Next.js 13.4 App Router approach)
My implementation is just a simplified version of the React Router's <Navigate/>
component. As noted in the React Router doc, "the v6 <Navigate />
uses push
logic by default and you may change it via replace
prop". So the default value for replace
in my implementation will be false
just for API consistency.
import {useRouter} from 'next/navigation'
import {useEffect} from 'react'
type NavigateProps = {to: string; replace?: boolean}
export default function Navigate({to, replace = false}: NavigateProps): null {
const router = useRouter()
useEffect(() => {
if (replace) {
router.replace(to)
} else {
router.push(to)
}
}, [replace, router, to])
return null
}
And you might consume it at the root layout that wraps all the routes and pages you want to protect (e.g. /protected/*
routes):
// /app/protected/layout.tsx
'use client'
import {useAuth} from '@scope/react-auth'
import {Fragment, ReactNode} from 'react'
import Navigate from '~/components/Navigate'
export default function Layout({children}: {children: ReactNode}) {
return <RequireLogin>{children}</RequireLogin>
}
function RequireLogin({children}: {children: ReactNode}) {
const {currentUser} = useAuth()
return <Fragment>{currentUser ? children : <Navigate to="/ap/login" replace />}</Fragment>
}
⚠️ According to one of the authors of react-router, using render
prop for private routes should be avoided in React Router v6.
⚠️ According to the new useRouter()
API, the new useRouter
hook should be imported from next/navigation
and not next/router
.