#Batch Updates
This example calls setValues multiple times in a row. Each patch is applied on top of the intermediate search params after the previous update, so it does not overwrite other fields.
Apply preset
The preset calls setValues three times in a row.
setValues({ keyword: 'router' });
setValues({ scope: 'guides' });
setValues({ tags: ['react', 'docs'] });import { useSearchValues } from '@guanriyue/decurl';
import { defineFields, field } from '@guanriyue/decurl/codec';
import {
elementOf,
length,
mapItems,
pipe,
trim,
unique,
} from '@guanriyue/decurl/decode';
import { RotateCcw, Sparkles } from 'lucide-react';
import { useLocation } from 'react-router';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
const fields = defineFields({
keyword: field({
name: 'example_batch_keyword',
decode: pipe(trim, length.min(1)),
}),
scope: field({
name: 'example_batch_scope',
decode: elementOf(['all', 'guides', 'api']),
defaultValue: 'all',
}),
tags: field({
name: 'example_batch_tag',
mode: 'multi',
decode: pipe(mapItems(elementOf(['react', 'router', 'docs'])), unique),
}),
});
const toSearchText = (search: string): string => {
return search.length > 0 ? search : '(empty)';
};
const BatchUpdates = () => {
const location = useLocation();
const [values, setValues] = useSearchValues(fields);
return (
<section className="mx-auto w-full max-w-4xl space-y-5 p-4">
<div className="grid gap-4 lg:grid-cols-[minmax(0,1fr)_20rem]">
<div className="space-y-4">
<div className="space-y-1.5">
<h2 className="text-base font-semibold">Apply preset</h2>
<p className="text-sm text-muted-foreground">
The preset calls setValues three times in a row.
</p>
</div>
<div className="flex flex-wrap gap-2">
<Button
type="button"
onClick={() => {
setValues({ keyword: 'router' });
setValues({ scope: 'guides' });
setValues({ tags: ['react', 'docs'] });
}}
>
<Sparkles />
Apply docs preset
</Button>
<Button
type="button"
variant="outline"
onClick={() => {
setValues({
keyword: undefined,
scope: undefined,
tags: undefined,
});
}}
>
<RotateCcw />
Reset
</Button>
</div>
<pre className="overflow-x-auto rounded-md bg-muted/40 p-3 text-xs">
<code>{`setValues({ keyword: 'router' });
setValues({ scope: 'guides' });
setValues({ tags: ['react', 'docs'] });`}</code>
</pre>
</div>
<aside className="min-w-0 space-y-4 rounded-md bg-muted/40 p-4 text-sm">
<div className="space-y-2">
<span className="font-medium">location.search</span>
<code className="block break-all rounded-md bg-background/70 px-2.5 py-2 font-mono text-xs">
{toSearchText(location.search)}
</code>
</div>
<div className="space-y-2">
<span className="font-medium">Decoded values</span>
<div className="flex flex-wrap gap-2">
<Badge variant="secondary">
keyword: {values.keyword ?? '-'}
</Badge>
<Badge variant="secondary">scope: {values.scope}</Badge>
<Badge variant="secondary">
tags: {values.tags?.join(', ') || '-'}
</Badge>
</div>
</div>
</aside>
</div>
</section>
);
};
export default BatchUpdates;