Karthi
Karthi

Reputation: 3489

Get URL pathname in nextjs

I have a signin page and layout component.Layout component has header.I don't want to show header in signin .and for that I want to get url pathname.based on pathname show the header .

import * as constlocalStorage from '../helpers/localstorage';
import Router from 'next/router';

export default class MyApp extends App {
    componentDidMount(){
        if(constlocalStorage.getLocalStorage()){
            Router.push({pathname:'/app'});
        } else{
            Router.push({pathname:'/signin'});
        }

    }

    render() {
        const { Component, pageProps } = this.props
        return (
//I want here pathname for checking weather to show header or not
                <Layout>
                    <Component {...pageProps} />
                </Layout>
        )
    }
}

please help

Upvotes: 160

Views: 413100

Answers (19)

Suben Saha
Suben Saha

Reputation: 1848

If you want to get url pathname in Server Component of app router in nextjs 13 or above, you can create a middleware in src or app or whatever root directory are you using like below:

import {NextRequest, NextResponse} from "next/server";

export function middleware(request: NextRequest) {
    request.headers.set("x-current-path", request.nextUrl.pathname);
    return NextResponse.next({ request });
}
export const config = {
    matcher: [
        // match all routes except static files and APIs
        "/((?!api|_next/static|_next/image|favicon.ico).*)",
    ],
};

Then use the following code in any layout or page file:

export default async function Layout() {
    const headerList = await headers();
    const pathname = headerList.get("x-current-path");
    return (
       <div>....</div>
    )
}

Upvotes: 1

kamal shakoor
kamal shakoor

Reputation: 21

This is how i just fetched the url and added active nav item feature in navbar

'use client'
import Link from 'next/link'
import React from 'react'
import Image from 'next/image'
import LogoImg from '../../assets/logo.png'
import classes from './main-header.module.css'
import { usePathname } from 'next/navigation'

const MainHeader = () => {
  const pathname = usePathname();

  return<>
    <header className={classes.header} >
      <nav className={classes.nav}>
        <ul className={classes.navList}>
          <li >
        <Link href="/meals/" className={pathname.startsWith('/meals') ? classes.active : ''}>BrowseMeal</Link>
      </li>
      <li>
        <Link href="/community/" className={pathname.startsWith('/community') ? classes.active : ''}>community</Link>
      </li>
        </ul>
      </nav>
    </header>
   
  </>
  
}

export default MainHeader

Upvotes: 1

Abdur Rakib Rony
Abdur Rakib Rony

Reputation: 77

In Client Components, you can use 'usePathname' is a Client Component hook that lets you read the current URL's pathname.

'use client'
import { usePathname } from 'next/navigation'
 
export default function ExampleClientComponent() {
  const pathname = usePathname()
  return <p>Current pathname: {pathname}</p>
}

In your Api's, Get query params and pathname:

export async function GET(req){
 const pathname = req.path
 console.log(pathname )

 const {searchParams} = new URL(req.url);
 const param1 = searchParams.get('param1');
 console.log(param1 )
}

Upvotes: 6

Mahmoud Khalil
Mahmoud Khalil

Reputation: 1

import { usePathname } from "next/navigation";

const pathName = usePathname();

Upvotes: 0

Aiman Farhan
Aiman Farhan

Reputation: 216

With Next 13 above

If you want to get the url from the server side.

Refer to this https://nextjs.org/docs/app/building-your-application/data-fetching/patterns

In my use-case, I have multi-tenant application that renders different styles based on the tenantId.

To retrieve this id, I run a function to fetch the tenantId from the url before passing it to the components.

Example below:

async function getSearchParams() {
  const headersInstance = headers();
  const pathname = headersInstance.get("referer");
  if (!pathname) return new URLSearchParams();
  const urlSearchParams = new URLSearchParams(pathname.split("?")[1]);
  return urlSearchParams;
}
async function getTenantId() {
  const searchParams = await getSearchParams();
  const tenantId = searchParams.get("tenantId");

  if (tenantId) {
    return tenantId;
  }
  return "";
}

Upvotes: 2

malik kurosaki
malik kurosaki

Reputation: 2042

for client side another way is

example url: https://www.example.com/some-page?param1=value1&param2=value2

...
useEffect(() => {
    if (window) {
      const currentURL = new URL(window.location.href);

      // host (domain)
      const host = currentURL.host;
      console.log('Host:', host);

      // path (path dari URL)
      const path = currentURL.pathname;
      console.log('Path:', path);

      // query (parameter dari URL)
      const query = currentURL.search;
      console.log('Query:', query);
    }
  }, [])

Upvotes: 2

Devin Rhode
Devin Rhode

Reputation: 25367

For next 13 server-side, I imported headers fn from next/headers and then did headers.get('x-invoke-path')

Upvotes: 1

Mahmoud Abd Al-Aziz
Mahmoud Abd Al-Aziz

Reputation: 109

For those who are migrating from Nextjs Page-Router to App-outer V13+

I was searching for the method to get the full URL

Hers is how it should be done as recommended by Nextjs Documentation

    'use client'
 
import { useEffect } from 'react'
import { usePathname, useSearchParams } from 'next/navigation'
 

    export function NavigationEvents() {
  const pathname = usePathname()
  const searchParams = useSearchParams()
 
  useEffect(() => {
    const url = `${pathname}?${searchParams}`
    console.log(url)
    // You can now use the current URL
    // ...
  }, [pathname, searchParams])
 
  return null
}

Notice that you should use this in a client component, not a server component which means you will need to add "use client" on the top of your component page.

In case you want to do this in a server component, you will need to pass the server component to a client component as props.

Scenario: You need the URL in a server component and you can't use the usePathname and useSearchParams as they are only allowed in client components So what do the docs recommend in this case (and any case where you want to do something in a server component that requires only a client component.

You do what you want in the client component and then pass the server component to the client component with a prop this prop value will be the value of the URL for example or any other data you want to pass to the server component)

Simple Explanation: you will add a prop to the server component called URL and in the client component you will pass the URL which you get using the usePathname and useSearchParams as a prop value to the URL prop.

And if you are thinking why not import the Server Component directly:

From the docs:

Unsupported Pattern: Importing Server Components into Client Components The following pattern is not supported. You cannot import a Server Component into a Client Component:

Here's an explanation from the Docs:

Passing Server Components to Client Components as Props

Links:

Docs about the new router updates: https://nextjs.org/docs/app/api-reference/functions/use-router

Docs about usePathname: https://nextjs.org/docs/app/api-reference/functions/use-pathname

Docs about useSearchParams: https://nextjs.org/docs/app/api-reference/functions/use-search-params

Upvotes: 5

Omanaite
Omanaite

Reputation: 39

Next.js v13.4.3

This worked for me

import { usePathname} from 'next/navigation'

const pathname = usePathname();

console.log(pathname)

Upvotes: 3

GMKHussain
GMKHussain

Reputation: 4711

If you are using Next.js 13

usePathname instead useRouter

'use client';

import { usePathname } from 'next/navigation';

export default function MyComponent() {
  const currentPage = usePathname();
  return <div>{currentPage}</div>;
}

Upvotes: 35

Bilal Haider Qureshi
Bilal Haider Qureshi

Reputation: 11

My app needed to have multiple documents, so I also was looking for a way to get the path name, with nextjs, default document This is a way that I found, which works for me.

import Document, { Html, Head, Main, NextScript } from 'next/document'
import { LandingPage, WithSidePanels } from '../documents'

class MyDocument extends Document {
    static async getInitialProps(ctx) {
        const initialProps = await Document.getInitialProps(ctx)
        return { ...initialProps }
    }
    
    
    render() {
        console.log(this.props.__NEXT_DATA__.page)
        if(this.props.__NEXT_DATA__.page === "/") return <LandingPage />


        return (
           <WithSidePanels />
        )
    }
}

export default MyDocument

So this.props.__NEXT_DATA__.page this is going to give you, the path name, "/", or "/contact" or whatever, from the _document.js :)

Upvotes: 1

acmoune
acmoune

Reputation: 3423

Might be late but just use router.pathname

function MyComp() {
    const router = useRouter();

    return (
        <a className={router.pathname === '/some-path' ? 'currentCSS' : 'defaultCSS'}>
            Some link
        </a>
    );
}

Upvotes: 9

Suraj Sharma
Suraj Sharma

Reputation: 857

Suppose the complete URL of a page is 'abc.com/blog/xyz' and the component file name matching with this route is './pages/blog/[slug].js'

useRouter() hook returns a route object, which has two properties to get the pathname.

  1. One is asPath property, and

  2. Another one is pathname property.

asPath property contains pathname extracted from the URL i.e. /blog/xyz

but pathname property contains the pathname of your project directory i.e. /blog/[slug].

Example Implementation

// .pages/blog/[slug].js

import { useRouter } from 'next/router';

const BlogSlug = () => {
  const { asPath, pathname } = useRouter();
  console.log(asPath); // '/blog/xyz'
  console.log(pathname); // '/blog/[slug]'
  return (
    <div></div>
  );
}

export default BlogSlug;

Upvotes: 58

maiprasadr
maiprasadr

Reputation: 31

One cannot access the Router or the useRouter() options to access the current path in app.js file. This is not client side rendered and hence the only way to access you current path would be to pass it from your getInitialProps() or the getServerSideProps() call to your App component, and then access it there to develop your logic based on the current route.

Upvotes: 3

imjared
imjared

Reputation: 20584

If you want to access the router object inside any functional component in your app, you can use the useRouter hook, here's how to use it:

import { useRouter } from 'next/router'

export default function ActiveLink({ children, href }) {
  const router = useRouter()
  const style = {
    marginRight: 10,
    color: router.pathname === href ? 'red' : 'black',
  }

  const handleClick = e => {
    e.preventDefault()
    router.push(href)
  }

  return (
    <a href={href} onClick={handleClick} style={style}>
      {children}
    </a>
  )
}

If useRouter is not the best fit for you, withRouter can also add the same router object to any component, here's how to use it:

import { withRouter } from 'next/router'

function Page({ router }) {
  return <p>{router.pathname}</p>
}

export default withRouter(Page)

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

Upvotes: 160

Ruslan Korkin
Ruslan Korkin

Reputation: 5131

You can use asPath property, that will give you the path (including the query) shown in the browser without the configured basePath or locale:

const { asPath } = useRouter()

Upvotes: 70

Wilker
Wilker

Reputation: 651

Probably to avoid use import Router from 'next/router' in nextjs you may use

import {useRouter} from 'next/router';

Upvotes: -5

M Fuat
M Fuat

Reputation: 1440

For whom who are searching for an example:

import React, { Component } from "react";
import { withRouter } from 'next/router'

class Login extends Component {


    constructor(props) {
        super(props);
    }


    onClickHandler = (event) => {
        this.props.router.push('/newPage')

    }

    render() {
        return (

            <div>
                <p>Hello, {this.props.router.pathname}</p>
                <button onClick={this.onClickHandler}>Click me!</button>
            </div>
        );
    }
}

export default withRouter(Login);

Upvotes: -1

Ga&#235;l S
Ga&#235;l S

Reputation: 1569

To fully use the SSR out-of-the-box provided by Next.js, you can use the context object provided in getInitialProps and which contains the pathname. You can then pass this pathname to be used as a props by your component.

For example:

class Page extends React.Component {
 static getInitialProps({ pathname }){
  return { pathname }
 }
 render() {
  return <div>{this.props.pathname === 'login' ? 'good' : 'not good'}</div>
 }
}

Upvotes: 9

Related Questions