Alfrex92
Alfrex92

Reputation: 6788

How to remove Query Params

How can I remove or update query params without refreshing the page in Next JS (React)?

  1. The user is on the URL /about?login=success&something=yes
  2. Click a button and removes ?login=success&something=yes from the URL without refreshing the page. The URL after clicking the button will be /about

How can I achieve it?

As mentioned in this thread, I know that is possible to remove query params or query strings with Router. But, useLocation and useHistory are not avaliable on next/router.

Upvotes: 49

Views: 126528

Answers (20)

dharmveer bangar
dharmveer bangar

Reputation: 61

'use client'

import { useSearchParams, usePathname, useRouter } from 'next/navigation'
import { Chip } from '@/components/ui/chip'

export default function FilterReset() {
  const searchParams = useSearchParams()
  const pathname = usePathname()
  const { replace } = useRouter()
  const customerFilterId = searchParams.get('customer')

  const handleResetFilters = () => {
    const params = new URLSearchParams(searchParams)
    params.delete('customer')
    replace(`${pathname}?${params.toString()}`)
  }

  if (!customerFilterId) {
    return null
  }

  return (
    <Chip
      onClose={handleResetFilters}
      variant="bordered"
      color="danger"
    >
      Reset
    </Chip>
  )
}

Upvotes: 0

clodal
clodal

Reputation: 1835

For Next.js 13 & above, you usually want to keep pathname and all other query params the same while deleting one specific query param (e.g. foo) you can do so like this:

'use client'

import { useRouter, usePathname, useSearchParams } from 'next/navigation'

const router = useRouter()
const pathname = usePathname()
const searchParams = useSearchParams()

const nextSearchParams = new URLSearchParams(searchParams.toString())
nextSearchParams.delete('foo')

router.replace(`${pathname}?${nextSearchParams}`)

(Upgraded answer of @sebastian-voráč-msc)

Upvotes: 18

SteffenK
SteffenK

Reputation: 712

Another approach is removing the query parameter server-side using a middleware function. With the app router you can create a middleware.js file inside your app directory with the following content:

import { NextResponse } from 'next/server';

export function middleware(req) {
    const url = req.nextUrl.clone();
    const value = url.searchParams.get('your_query_parameter')

    if (value) {
        url.searchParams.delete('your_query_parameter')
        return NextResponse.redirect(url);
    }
    
    return NextResponse.next();
}

Upvotes: 1

antokhio
antokhio

Reputation: 2004

My case is canonical url, so should be available on build, the approach:

const router = useRouter();
const url = new URL(PUBLIC_URL + router.asPath);
const canonicalUrl = PUBLIC_URL + url.pathname; 

note: this using pages

Upvotes: 0

Divins Mathew
Divins Mathew

Reputation: 3186

For Next 13+, if you're working with the app router, you'll have to use a combination of useSearchParams, usePathname, URLSearchParams, and useRouter from next/navigation to achieve this.

import { usePathname, useRouter, useSearchParams } from "next/navigation";

const router = useRouter();
const pathname = usePathname();
const query = useSearchParams();

const params = new URLSearchParams(query);

//do your modifications on search params
params.delete("search");

const newUrl = `${pathname}?${params.toString()}`;
router.replace(newUrl);

Reference.

Upvotes: 1

Albedo-13
Albedo-13

Reputation: 1

Since router.query is a simple object, you can delete query params by mutating router.query.

Lets say you have query params ?size=M&color=red:

// INIT

const router = useRouter();
router.push({ 
  pathname: router.pathname, 
  query: { ...router.query, color: "red", size: "M" }
},
  undefined, 
  {}
);

And you need to remove only ONE param, for example size=M. All you need to do is directly delete the field from router.query object and push your mutation (spread operator to keep all other params):

// DELETE ONE

delete router.query.color;
router.push({
  pathname: router.pathname,
  query: { ...router.query }
},
  undefined,
  {}
);

If you want to remove ALL params, just simply push null to query field:

// DELETE ALL

router.push({
  pathname: router.pathname,
  query: null
},
  undefined,
  {}
);

Upvotes: 0

Anurag Tripathi
Anurag Tripathi

Reputation: 1094

We can use useRouter hook from next/router to access the current route and query parameters. To remove or update parameters without refreshing the page, we can use the push method of the router object.

Here is an example of how we can remove query parameters from the URL:

const router = useRouter();
  function removeQueryHandler() {
    const { pathname } = router;

    router.push({ pathname });
}

CodeSandbox: link

Another Approach:

We can use shallow routing as well to remove or update query parameters without triggering a full page refresh in Next.js. Like this:

function removeQueryHandler() {
    const { pathname } = router;

    router.push({ pathname }, undefined, { shallow: true });
  }

Upvotes: 2

Maybe this solution will be a bit more neat:

const { query, replace } = useRouter();
const setActiveTab = useCallback((tabName: string) => {
    const { group, ...paramsExceptGroup } = query || {};
    replace(
      {
        query: tabName === defaultTabName ? paramsExceptGroup : { ...paramsExceptGroup, group: tabName },
      },
      undefined,
      { shallow: true },
    ).then();
  }, [query, defaultTabName]);

So if "tab" is default, I drop it with spread operator and remove it from query.

Upvotes: 1

Sumit Wadhwa
Sumit Wadhwa

Reputation: 3217

This should work for you well:

router.replace('/about', undefined, { shallow: true });

The shallow routing will not cause page refresh and data refetch. Learn more here.

Even though the above solution removes the query params without causing a refresh, they do cause re-render.

Unfortunately, Nextjs has no built in solution to remove query param without causing a re-render. But, there's a native solution:

window.history.replaceState({ ...window.history.state, as: '/about', url: '/about' }, '', '/about');

Upvotes: 2

juliomalves
juliomalves

Reputation: 50338

You can use next/router to remove the query params in the URL.

const router = useRouter();

router.replace('/about', undefined, { shallow: true });

Use replace to prevent adding a new URL entry into the history (otherwise just use push), and shallow: true allows you to change the URL without running data fetching methods. This will cause a re-render but will not refresh the page per se.


The above solution will remove all query parameters from the URL. If you want to only remove a specific parameter you can use the code below instead.

const removeQueryParam = (param) => {
    const { pathname, query } = router;
    const params = new URLSearchParams(query);
    params.delete(param);
    router.replace(
        { pathname, query: params.toString() },
        undefined, 
        { shallow: true }
    );
};

removeQueryParam('something');

Upvotes: 81

Patrick
Patrick

Reputation: 73

For next/router, along with typescript, none of the above answers seem to be working anymore.

The following snippet takes all query parameters and removes one by the key while keeping all others untouched.

const { push, query } = useRouter();


const removeQueryParam = (param) => {
    const updatedQuery = query;
    delete updatedQuery[param];

    push({ query: updatedQuery }, undefined, { shallow: true });
}

Usage (in clickHandler or wherever):

removeQueryParam('queryParamName');

Note: Use router.replace instead of router.push if you don't want to add the new URL to the browser history back stack.

Upvotes: 3

Oussamah J
Oussamah J

Reputation: 1

Good way to do it when you know the query param you want to remove based on https://github.com/jbranchaud/til/blob/master/nextjs/remove-a-query-param-from-the-url.md

    const router = useRouter();

    useEffect(() => {
    // extract the value from the query params
    const { someKey, ...updatedQuery } = router.query;
    
    // create an updated router path object
    const newPathObject = {
      pathname: router.pathname,
      query: updatedQuery,
    };
    
    // update the URL, without re-triggering data fetching
    void router.push(newPathObject, undefined, { shallow: true });

  }, [router]);

Upvotes: 0

Muhammet Can TONBUL
Muhammet Can TONBUL

Reputation: 3538

If you want remove single or multiple params from query,

const router = useRouter();

/**
 * If removeList is empty, the function removes all params from url.
 * @param {*} router 
 * @param {*} removeList 
 */
const removeQueryParamsFromRouter = (router, removeList = []) => {
    if (removeList.length > 0) {
        removeList.forEach((param) => delete router.query[param]);
    } else {
        // Remove all
        Object.keys(router.query).forEach((param) => delete router.query[param]);
    }
    router.replace(
        {
            pathname: router.pathname,
            query: router.query
        },
        undefined,
        /**
         * Do not refresh the page
         */
        { shallow: true }
    );
};

const anyFunction = () => {
    // "/about?firstParam=5&secondParam=10"
    removeQueryParamsFromRouter(router, ['myParam']);
    // "/about?secondParam=10"
};

Upvotes: 5

Sebastian Vorac
Sebastian Vorac

Reputation: 4693

You usually want to keep pathname and all other query params the same while deleting one specific query param (in example shouldRefetchUser) you can do so like this:

const router = useRouter()
const { pathname, query } = router
delete router.query.shouldRefetchUser
router.replace({ pathname, query }, undefined, { shallow: true })

(Upgraded answer of @juliomalves)

Upvotes: 9

Gowdham PR
Gowdham PR

Reputation: 59

You can simply use "router.push" or "router.replace" with "shallow: true", this will remove the query param without reloading the page.

const router = useRouter();
router.replace('/about', undefined, { shallow: true });

Or if you want to delete single query then this quick and easy method will help you

eg. /about?login=success&something=yes

const router = useRouter();
// perform this inside function call or button click etc
delete router.query.something;
router.push(router)

now the updated route will be

/about?login=success

Upvotes: 4

Chindukuri Pavan
Chindukuri Pavan

Reputation: 99

import {NextRouter} from 'next/router'

export const removeQueryParams = (
  router: NextRouter,
  paramsToRemove: Array<string> = []
) => {
  if (paramsToRemove.length > 0) {
    paramsToRemove.forEach((param) => delete router.query[param])
  } else {
    // Remove all query parameters
    Object.keys(router.query).forEach((param) => delete router.query[param])
  }
  router.replace(
    {
      pathname: router.pathname,
      query: router.query,
    },
    undefined,
    /**
     * Do not refresh the page when the query params are removed
     */
    {shallow: true}
  )
}
const anyFunction = () => {
    // "/about?firstParam=5&secondParam=10"
    removeQueryParamsFromRouter(router, ['myParam']);
    // "/about?secondParam=10"
};

Original Answer

The original answer mentioned here throws an error as the object is undefined, also it is the typescript version of it.

Upvotes: 0

Hossein
Hossein

Reputation: 4559

You can remove query param from router object by []:

const router = useRouter();
router.query.something = [];

Upvotes: 0

James Gunawan
James Gunawan

Reputation: 167

my solution to similiar problem of mine is this:

push(`${asPath.split('?')[0]}?comp=${id}`);

or if you want to have reusable function:


function delQuery(asPath) {
  return asPath.split('?')[0]
}

...
const {push, asPath} = useRouter()

push(`${delQuery(asPath)}?comp=${id}`);

Upvotes: 7

Jack Chen
Jack Chen

Reputation: 680

According to the History, you can using history.replaceState to implement this.

window.history.replaceState(null, '', '/about')

Upvotes: 13

Jibin Thomas
Jibin Thomas

Reputation: 864

Nextjs has useRouter hook which can be used to changed url programmatically. Link to the docs.

Upvotes: -2

Related Questions