Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion: useSearchParamState #9

Open
iamnafets opened this issue Feb 5, 2024 · 7 comments
Open

Suggestion: useSearchParamState #9

iamnafets opened this issue Feb 5, 2024 · 7 comments
Labels
enhancement New feature or request question Further information is requested

Comments

@iamnafets
Copy link

iamnafets commented Feb 5, 2024

Sometimes it's useful to use the search params to store state. We currently have something like this:

    const [query, setQuery] = useSearchParamState('query', z.string(), "defaultQuery");

Where setQuery actually changes the search params and updates the state. I'd love to incorporate this into the library. Any interest?

Thinking this look like:

export const { routes, useSafeParams, useSearchParamsState } = createNavigationConfig(
   // ...
)

const [{ query, page }, setSearchParams] = useSearchParamsState('search');
@lukemorales
Copy link
Owner

Thanks for another great suggestion @iamnafets!

Could you elaborate a bit more over how would this be different/better than using:

export const { routes, useSafeParams, useSearchParamsState } = createNavigationConfig(defineRoute => ({
   search: defineRoute('/search', { search: z.object({ query: z.string(), page: z.coerce.number() })  })
}));

// Search Page

export default function SeachPage() {
  // ...
  return (
    <Pagination>
      <Link href={routes.search({ search: { query, page: page + 1 } })}>Next page</Link>
    </Pagination>
  )
}

@lukemorales lukemorales added enhancement New feature or request question Further information is requested labels Feb 5, 2024
@iamnafets
Copy link
Author

For SPAs, you often want to manipulate the querystring without navigating. React's Dispatch<SetActionState<T>> takes a lambda which passes the current value allowing you to do something like setSearchParams(old => ({ ...old, page: old.page +1 })) instead of re-assembling the whole object for if your queryString becomes large.

@lukemorales
Copy link
Owner

lukemorales commented Feb 5, 2024

For SPAs, you often want to manipulate the querystring without navigating.

How come? I mean, what's the point of storing state in the URL if you're not navigating?

@jthrilly
Copy link

jthrilly commented Jun 10, 2024

How come? I mean, what's the point of storing state in the URL if you're not navigating?

There are quite a few situations where you'd want to do this. We use it for query parameters for filtering a table. The general idea is that by having state reflected in the URL, you can make your URLs much more useful for sharing purposes. There's a great lib, nuqs (https://nuqs.47ng.com/), which I use extensively for this.

Actually, I came here to suggest considering integration with nuqs. It would be incredibly powerful to be able to define nuqs style query state for a route, and then use the hooks it provides for getting/setting searchParams, while keeping the validation checks provided by the current implementation.

@lukemorales
Copy link
Owner

There are quite a few situations where you'd want to do this. We use it for query parameters for filtering a table. The general idea is that by having state reflected in the URL, you can make your URLs much more useful for sharing purposes. There's a great lib, nuqs (https://nuqs.47ng.com/), which I use extensively for this.

Yes, I get the point of having state reflect in the URL but I strongly disagree that there are any situations where a query parameter changing doesn't reflect on browser navigation

@jthrilly
Copy link

Yes, I get the point of having state reflect in the URL but I strongly disagree that there are any situations where a query parameter changing doesn't reflect on browser navigation

Well, this is precisely how nextJS used to work: https://nextjs.org/docs/pages/building-your-application/routing/linking-and-navigating#shallow-routing

This is really a semantic issue. Changing the query does reflect on "browser navigation" - but only on first load. After that, updates can optionally be done "client first", so that you can use query parameters as direct replacements for useState. You then get the best of all worlds (deterministic initial state, and better UX when state changes).

@Katona
Copy link
Contributor

Katona commented Aug 16, 2024

I think one difference might be that a useSearchParamState could maintain the rest of the params. So for instance, if the current page has many query params, then changing only one would require something like this:

  setSearchParams({ page: page + 1 });

vs

  routes.search({ 
    page: page + 1, 
    query, 
    sort
    // etc
  });

But I believe this could be built on top of this library.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request question Further information is requested
Projects
None yet
Development

No branches or pull requests

4 participants