Filtering using search params
Answered
Pumi posted this in #help-forum
PumiOP
Hello!
I'm new to React and Next.js so bear with me, I'm coming from years of Angular.
I want to build a filter where users can search and filter the results of a list, a simple input for now.
This is my page
And this is my filter component
The problem is that the page seems to get stuck, and stops updating the url after it has been changed a few times. I don't get any errors though.
I'm new to React and Next.js so bear with me, I'm coming from years of Angular.
I want to build a filter where users can search and filter the results of a list, a simple input for now.
This is my page
'use cache';
import { Suspense } from 'react';
import { OrganisationsFilter } from './components/organisations-filter';
export default async function Home({ searchParams }: Readonly<{ searchParams: Promise<{ query: string }> }>) {
const { query } = await searchParams;
return (
<Suspense>
<main className="p-4">
<OrganisationsFilter />
</main>
</Suspense>
);
}
And this is my filter component
'use client';
import { useEffect, useState } from 'react';
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { useDebounce } from 'use-debounce';
import { Input } from '@/components/ui/input';
export function OrganisationsFilter() {
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();
const [query, setQuery] = useState(searchParams.get('query') || '');
const [debouncedQuery] = useDebounce(query, 500);
useEffect(() => {
const searchParams = new URLSearchParams();
if (debouncedQuery) {
searchParams.set('query', debouncedQuery);
}
router.push(`${pathname}?${searchParams.toString()}`);
}, [debouncedQuery]);
return (
<div>
<Input placeholder="Sök organisation..." onChange={(e) => setQuery(e.target.value)} />
</div>
);
}
The problem is that the page seems to get stuck, and stops updating the url after it has been changed a few times. I don't get any errors though.
31 Replies
https://nuqs.47ng.com/
try this out
try this out
Answer
PumiOP
Looks promising, out picking up kids at the moment, will get back to you!
PumiOP
@James4u (Tag me if needed) This seems to solve the issue with the query params not updating after a while, however, the page is not reloading now as the search params change. Am I supposed to also push to the router to trigger data refetching?
This is my updated code
Filter
Page
Filter
'use client';
import { useQueryState } from 'nuqs';
import { Input } from '@/components/ui/input';
export function OrganisationsFilter() {
const [query, setQuery] = useQueryState('query', { defaultValue: '' });
return (
<div>
<Input placeholder="Sök organisation..." value={query} onChange={(e) => setQuery(e.target.value)} />
</div>
);
}
Page
export default async function Home({ searchParams }: Readonly<{ searchParams: Promise<{ query: string }> }>) {
const { query } = await searchParams;
const organisations = await db.query.organisationsTable.findMany({
where: (table, { eq }) => {
if (query) {
return eq(table.name, query);
}
return undefined;
},
});
return (
<Suspense>
<main className="p-4">
<OrganisationsFilter />
{organisations.map((org, orgIndex) => (
<div key={orgIndex}>{org.name}</div>
))}
</main>
</Suspense>
);
}
yeah, you need
router.refresh()
PumiOP
I assume the best course of action is to do that in a useEffect then, and maybe even debounce the value from the useQueryState?
yeah, if you don't have submit button - that would be the best choice
and yeah debounce it
PumiOP
Am I supposed to have
I get this error otherwise
'use cache';
at the top of such pages?I get this error otherwise
Error: Route "/": A component accessed data, headers, params, searchParams, or a short-lived cache without a Suspense boundary nor a "use cache" above it. We don't have the exact line number added to error messages yet but you can see which component in the stack below. See more info: https://nextjs.org/docs/messages/next-prerender-missing-suspense
hmm are you using canary?
PumiOP
I am, yes
I'm starting to think maybe I shouldn't?
check out this, you can wrap your component by <Suspense />
I think it should be better than trying "use cache"
PumiOP
But my whole page is wrapped in Suspense, is that wrong maybe and just the filter component should be?
import { Suspense } from 'react';
import { OrganisationsFilter } from './components/organisations-filter';
import { getPublicOrganisationsByNameAction } from '@/lib/actions/organisations/organisations.actions';
export default async function Home({ searchParams }: Readonly<{ searchParams: Promise<{ query: string }> }>) {
const { query } = await searchParams;
const organisations = await getPublicOrganisationsByNameAction(query);
return (
<Suspense fallback={<div>Laddar...</div>}>
<main className="p-4">
<OrganisationsFilter />
{organisations.map((org, orgIndex) => (
<div key={orgIndex}>{org.name}</div>
))}
</main>
</Suspense>
);
}
With this I am still getting the error
Error: Route "/": A component accessed data, headers, params, searchParams, or a short-lived cache without a Suspense boundary nor a "use cache" above it. We don't have the exact line number added to error messages yet but you can see which component in the stack below. See more info: https://nextjs.org/docs/messages/next-prerender-missing-suspense
I think you should follow this structure
import { Suspense } from 'react'
async function TransactionList() {
const transactions = await db.query(...)
return ...
}
function TransactionSkeleton() {
return <ul>...</ul>
}
export default async function Page() {
return (
<Suspense fallback={<TransactionSkeleton />}>
<TransactionList/>
</Suspense>
)
}
PumiOP
I see, split things up more
Ill try
PumiOP
This seems to work great now. Thanks a lot for the help! "Thinking in react/next.js" is hard coming from ~8 years of angular.
haha no worries! great!
Mark solution to close this thread if you don't have any other questions 🙂
wow, amazing! @Pumi You should be a master of Angular
PumiOP
Angular is a breeze for me, yes. But I like to experiment with other stuff and next has caught my eye, so I’m giving it a shot!
I don't know much about Angulr - but I know you should like Next.js
PumiOP
Great! I think I will too when I get into the mental model of it a bit more. Have a good evening! :)
you too! I actually want to hear from soneone who mastered two JS frameworks (Vue or Ang, or Remix, Next)
hope you will be the one soon
PumiOP
I'll let you know if I do! ;)