33

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.

Marioanzas
  • 1,663
  • 2
  • 10
  • 33
Alfrex92
  • 6,278
  • 9
  • 31
  • 51
  • does window.history.replaceState work for you? I tried it too, but when query params exist, next.js will force the url to revert – Rapidturtle Mar 12 '21 at 04:10

14 Answers14

67

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');
juliomalves
  • 42,130
  • 20
  • 150
  • 146
9

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

window.history.replaceState(null, '', '/about')
Jack Chen
  • 624
  • 5
  • 14
7

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}`);

James Gunawan
  • 167
  • 1
  • 5
6

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)

Sebastian Voráč MSc.
  • 3,256
  • 1
  • 18
  • 25
5

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"
};

juliomalves
  • 42,130
  • 20
  • 150
  • 146
Muhammet Can TONBUL
  • 3,217
  • 3
  • 25
  • 37
3

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

Gowdham PR
  • 49
  • 2
2

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.

Patrick
  • 63
  • 6
1

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.

1

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 });
  }
Anurag Tripathi
  • 784
  • 1
  • 13
  • 13
0

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

const router = useRouter();
router.query.something = [];
Hossein
  • 3,755
  • 2
  • 29
  • 39
0
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.

0

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]);
0

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');
Sumit Wadhwa
  • 2,825
  • 1
  • 20
  • 34
-2

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

Jibin Thomas
  • 775
  • 3
  • 9
  • 25