#persising search params

1 messages · Page 1 of 1 (latest)

rancid echo
#

how do i persist search params when navigation with next/link

ember shoreBOT
#

Hi @rancid echo. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

To persist search parameters when navigating with next/link, you can use the useRouter or Link to set new searchParams. After a navigation is performed, the current page will receive an updated searchParams prop.

Here's an example of how you can do this:

export default function ExampleClientComponent() {
 const router = useRouter()
 const pathname = usePathname()
 const searchParams = useSearchParams()!
 
 // Get a new searchParams string by merging the current
 // searchParams with a provided key/value pair
 const createQueryString = useCallback(
 (name: string, value: string) => {
 const params = new URLSearchParams(searchParams)
 params.set(name, value)
 
 return params.toString()
 },
 [searchParams]
 )
 
 return (
 <>
 <p>Sort By</p>
 
 {/* using useRouter */}
 <button
 onClick={() => {
 // <pathname>?sort=asc
 router.push(pathname + '?' + createQueryString('sort', 'asc'))
 }}
 >
 ASC
 </button>
 
 {/* using <Link> */}
 <Link
 href={
 // <pathname>?sort=desc
 pathname + '?' + createQueryString('sort', 'desc')
 }
 >
 DESC
 </Link>
 </>
 )
}

In this example, a new searchParams string is created by merging the current searchParams with a provided key/value pair. This new string is then used to navigate to a new page with the updated search parameters.

For more information, you can refer to the Next.js documentation on useSearchParams (https://nextjs.org/docs/app/api-reference/functions/use-search-params).

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@rancid echo kapa.ai is still learning and improving, please let us know how it did by reacting below

rancid echo
#

@ember shore rather smth like this and pass children and classname as well

import * as React from 'react';

import Link, { LinkProps } from 'next/link';
import { useSearchParams } from 'next/navigation';

export default function RetainQueryLink({
href,
...props
}: LinkProps) {
const searchParams = useSearchParams()!;

const persistQueryString = React.useCallback(() => {
const params = new URLSearchParams(searchParams);

return params.toString();

}, [searchParams]);

return (
<Link href={${href}?${persistQueryString()}} {...props}>
{props.}
</Link>
);
}

ember shoreBOT
#

Let me check the knowledge base for you. One moment! :books:

#

Your code is almost correct. You just need to pass children and className to the Link component. Here's the corrected code:

import * as React from 'react';
import Link, { LinkProps } from 'next/link';
import { useSearchParams } from 'next/navigation';

interface RetainQueryLinkProps extends LinkProps {
  children: React.ReactNode;
  className?: string;
}

export default function RetainQueryLink({
  href,
  children,
  className,
  ...props
}: RetainQueryLinkProps) {
  const searchParams = useSearchParams()!;

  const persistQueryString = React.useCallback(() => {
    const params = new URLSearchParams(searchParams);

    return params.toString();
  }, [searchParams]);

  return (
    <Link href={`${href}?${persistQueryString()}`} className={className} {...props}>
      {children}
    </Link>
  );
}

In this code, RetainQueryLinkProps extends LinkProps and adds children and className properties. These properties are then passed to the Link component in the return statement. The persistQueryString function is used to retain the query parameters when navigating to a new page.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@rancid echo kapa.ai is still learning and improving, please let us know how it did by reacting below

rancid echo
#

now make an additional that can be used for buttons with router push @ember shore

ember shoreBOT
#

Let me check the knowledge base for you. One moment! :books:

#

Sure, you can create a similar component for buttons that uses router.push to navigate. Here's an example:

import * as React from 'react';
import { useRouter } from 'next/router';
import { useSearchParams } from 'next/navigation';

interface RetainQueryButtonProps {
  href: string;
  children: React.ReactNode;
  className?: string;
}

export default function RetainQueryButton({
  href,
  children,
  className,
  ...props
}: RetainQueryButtonProps) {
  const router = useRouter();
  const searchParams = useSearchParams()!;

  const persistQueryString = React.useCallback(() => {
    const params = new URLSearchParams(searchParams);

    return params.toString();
  }, [searchParams]);

  const handleClick = (e: React.MouseEvent) => {
    e.preventDefault();
    router.push(`${href}?${persistQueryString()}`);
  };

  return (
    <button onClick={handleClick} className={className} {...props}>
      {children}
    </button>
  );
}

In this code, RetainQueryButtonProps defines the properties for the button component. The handleClick function is used to handle the button click event, it prevents the default event, then uses router.push to navigate to the new page with the retained query parameters. The persistQueryString function is used to retain the query parameters when navigating to a new page.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:

#

@rancid echo kapa.ai is still learning and improving, please let us know how it did by reacting below

rancid echo
#

@rancid echo i have a list item which contains a link that uses router push and has instance of router. is this bad cus im creating one instance for each link (list), which there can be a lot of

#

@ember shore i have a list item which contains a link that uses router push and has instance of router. is this bad cus im creating one instance for each link (list), which there can be a lot of

ember shoreBOT
#

Let me check the knowledge base for you. One moment! :books:

#

No, it's not bad. The useRouter hook doesn't create a new instance of the router for each component that uses it. Instead, it provides access to the single, existing router instance.

When you call useRouter in your components, you're not creating a new router object. You're simply retrieving the existing router object that's part of the Next.js context. This means you can use useRouter in as many components as you want without worrying about performance issues related to creating multiple router instances.

Here's an example of how you might use useRouter in a list of links:

import { useRouter } from 'next/router'

function ListItem({ href, children }) {
  const router = useRouter()

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

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

export default function List({ items }) {
  return (
    <ul>
      {items.map((item) => (
        <ListItem key={item.id} href={`/item/${item.id}`}>
          {item.name}
        </ListItem>
      ))}
    </ul>
  )
}

In this example, each ListItem component uses useRouter, but they all share the same router instance.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: