diff --git a/ui/params/filter.tsx b/ui/params/filter.tsx
new file mode 100644
index 00000000..cb738d87
--- /dev/null
+++ b/ui/params/filter.tsx
@@ -0,0 +1,21 @@
+'use client';
+
+import type { ReactNode } from 'react';
+
+import { Inline } from '../inline';
+import { Spinner } from '../spinner';
+import { ParamsProvier, useParamsContext } from './useParams';
+
+const Loading = () => {
+ const { pending } = useParamsContext();
+ return pending ?
: null;
+};
+
+export const Filter = ({ children }: { children?: ReactNode }) => (
+
+
+
+ {children}
+
+
+);
diff --git a/ui/params/useParams.tsx b/ui/params/useParams.tsx
index 3b3a45cf..97196186 100644
--- a/ui/params/useParams.tsx
+++ b/ui/params/useParams.tsx
@@ -1,6 +1,29 @@
'use client';
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
+import { createContext, useContext, useTransition } from 'react';
+import type { ReactNode, TransitionStartFunction } from 'react';
+
+// Context
+// ---------------
+const Context = createContext<{
+ pending: boolean;
+ startTransition: TransitionStartFunction;
+}>({} as any);
+
+export const useParamsContext = () => useContext(Context);
+
+// Provider
+// ---------------
+export const ParamsProvier = ({ children }: { children?: ReactNode }) => {
+ const [pending, startTransition] = useTransition();
+
+ return (
+
+ {children}
+
+ );
+};
// Hook
// ---------------
@@ -8,6 +31,7 @@ export const useParams =
(keys: Params[]) => {
const router = useRouter();
const pathname = usePathname();
const searchParams = useSearchParams();
+ const { startTransition } = useParamsContext();
const params = {} as { [param in Params]: string | null };
keys.forEach(key => {
@@ -28,7 +52,9 @@ export const useParams = (keys: Params[]) => {
const ps = sp.toString();
const queryString = `${ps.length ? '?' : ''}${ps}`;
- router.replace(`${pathname}${queryString}`, { scroll: false });
+ startTransition(() => {
+ router.replace(`${pathname}${queryString}`, { scroll: false });
+ });
};
return [params, setParams] as const;