How to add loader to Search debouncer
Answered
Yellowstripe scad posted this in #help-forum
Yellowstripe scadOP
export default function Search() {
const searchParams = useSearchParams();
const { replace } = useRouter();
const pathname = usePathname();
const handleSearch = useDebouncedCallback((term) => {
const params = new URLSearchParams(searchParams);
params.set('page', '1');
if (term) {
params.set('query', term);
} else {
params.delete('query');
}
replace(`${pathname}?${params.toString()}`);
}, 300);
return (
<>
<Input
type="text"
placeholder="Search"
className="w-full h-12"
onChange={(e) => {
handleSearch(e.target.value);
}}
defaultValue={searchParams.get('query')?.toString()}
/>
</>
)
}I want to add a loader, which is the component <Loader /> I have imported. I'm not sure how to make that work.
Answered by Ray
export default function Search() {
const searchParams = useSearchParams();
const { replace } = useRouter();
const pathname = usePathname();
const [isPending, startTransition] = useTransition()
const handleSearch = useDebouncedCallback((term) => {
const params = new URLSearchParams(searchParams);
params.set('page', '1');
if (term) {
params.set('query', term);
} else {
params.delete('query');
}
startTransition(() => {
replace(`${pathname}?${params.toString()}`);
})
}, 300);
return (
<>
{isPending && <span>loading...</span>}
<Input
type="text"
placeholder="Search"
className="w-full h-12"
onChange={(e) => {
handleSearch(e.target.value);
}}
defaultValue={searchParams.get('query')?.toString()}
/>
</>
)
}11 Replies
@Yellowstripe scad ts
export default function Search() {
const searchParams = useSearchParams();
const { replace } = useRouter();
const pathname = usePathname();
const handleSearch = useDebouncedCallback((term) => {
const params = new URLSearchParams(searchParams);
params.set('page', '1');
if (term) {
params.set('query', term);
} else {
params.delete('query');
}
replace(`${pathname}?${params.toString()}`);
}, 300);
return (
<>
<Input
type="text"
placeholder="Search"
className="w-full h-12"
onChange={(e) => {
handleSearch(e.target.value);
}}
defaultValue={searchParams.get('query')?.toString()}
/>
</>
)
}
I want to add a loader, which is the component <Loader /> I have imported. I'm not sure how to make that work.
export default function Search() {
const searchParams = useSearchParams();
const { replace } = useRouter();
const pathname = usePathname();
const [isPending, startTransition] = useTransition()
const handleSearch = useDebouncedCallback((term) => {
const params = new URLSearchParams(searchParams);
params.set('page', '1');
if (term) {
params.set('query', term);
} else {
params.delete('query');
}
startTransition(() => {
replace(`${pathname}?${params.toString()}`);
})
}, 300);
return (
<>
{isPending && <span>loading...</span>}
<Input
type="text"
placeholder="Search"
className="w-full h-12"
onChange={(e) => {
handleSearch(e.target.value);
}}
defaultValue={searchParams.get('query')?.toString()}
/>
</>
)
}Answer
you can do it with
useTransition hook@Ray ts
export default function Search() {
const searchParams = useSearchParams();
const { replace } = useRouter();
const pathname = usePathname();
const [isPending, startTransition] = useTransition()
const handleSearch = useDebouncedCallback((term) => {
const params = new URLSearchParams(searchParams);
params.set('page', '1');
if (term) {
params.set('query', term);
} else {
params.delete('query');
}
startTransition(() => {
replace(`${pathname}?${params.toString()}`);
})
}, 300);
return (
<>
{isPending && <span>loading...</span>}
<Input
type="text"
placeholder="Search"
className="w-full h-12"
onChange={(e) => {
handleSearch(e.target.value);
}}
defaultValue={searchParams.get('query')?.toString()}
/>
</>
)
}
Yellowstripe scadOP
its a bit laggy / flickery, how can I reduce this/make it smoother
like it is loading if the user isnt done typing
@Yellowstripe scad like it is loading if the user isnt done typing
could you show the code you have now?
Yellowstripe scadOP
"use client"
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { Input } from "./ui/input"
import { useDebouncedCallback } from 'use-debounce';
import { useState, useTransition } from 'react';
import Loading from './Loading';
export default function Search() {
const searchParams = useSearchParams();
const { replace } = useRouter();
const pathname = usePathname();
const [isPending, startTransition] = useTransition()
const handleSearch = useDebouncedCallback((term) => {
const params = new URLSearchParams(searchParams);
params.set('page', '1');
if (term) {
params.set('query', term);
} else {
params.delete('query');
}
startTransition(() => {
replace(`${pathname}?${params.toString()}`);
})
}, 300);
return (
<>
{isPending && <Loading/>}
<Input
type="text"
placeholder="Search"
className="w-full h-12"
onChange={(e) => {
handleSearch(e.target.value);
}}
defaultValue={searchParams.get('query')?.toString()}
/>
</>
)
}@Ray
what do you mean laggy / flickery?
Yellowstripe scadOP
if I type something into the search bar, quickly delete it and type something else the entire search bar lags. also, every letter I add it starts loading. I want to make it so it only loads when it detects typing stop if possible
@Ray try to increase the debounce time
Yellowstripe scadOP
worked! thank you!