Samyar
Samyar

Reputation: 533

react-router Navigate component in Nextjs

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

Upvotes: 6

Views: 3798

Answers (3)

Son Nguyen
Son Nguyen

Reputation: 4426

(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.

Upvotes: 3

LGBQT Destroyer
LGBQT Destroyer

Reputation: 38

you can use router.replace if u dont wwant to push but it will have a flaw that it will overwrite the current route

router.replace(url, as, options)

Upvotes: 1

Paweł Jadach
Paweł Jadach

Reputation: 21

https://nextjs.org/docs/api-reference/next/router

router.push(url, as, options)

Is that what you mean?

Upvotes: 0

Related Questions