Next.js Discord

Discord Forum

Filtering using search params

Answered
Pumi posted this in #help-forum
Open in Discord
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
'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.
Answered by James4u
View full answer

31 Replies

Answer
PumiOP
Looks promising, out picking up kids at the moment, will get back to you!
PumiOP
@James4u 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
'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>
    );
}
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 '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!
Original message was deleted
Mark solution to close this thread if you don't have any other questions 🙂
@James4u wow, amazing! <@198832691402113024> 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!
@James4u 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! :)
@Pumi 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! ;)