T
TanStack2y ago
stormy-gold

useSearchState a good idea for a hook?

So I've been messing around a bit and felt the need to build this thing. It works really well for me so far, but I don't know tanstack router well enough to know if it's a naive idea or actually a good idea:
import type {
AnyRoute,
FullSearchSchema,
NavigateOptions,
RegisteredRouter,
RouteApi,
RouteIds,
} from "@tanstack/react-router";
import { useNavigate } from "@tanstack/react-router";
import { useCallback } from "react";

type SearchParams<R extends AnyRoute> = FullSearchSchema<R>;

type SetSearchParams<R extends AnyRoute> = (
changes: Partial<SearchParams<R>>,
options?: Omit<NavigateOptions, "to" | "search">,
) => Promise<void>;

export function useSearchState<
TId extends RouteIds<RegisteredRouter["routeTree"]>,
TRoute extends AnyRoute,
>(
route: RouteApi<TId, TRoute>,
): [SearchParams<TRoute>, SetSearchParams<TRoute>] {
const navigate = useNavigate();
const search: SearchParams<TRoute> = route.useSearch();
const setSearch: SetSearchParams<TRoute> = useCallback(
(changes, options) =>
navigate({
to: route.id as string,
search: { ...search, ...changes },
...options
}),
[navigate, route.id, search],
);
return [search, setSearch];
}
import type {
AnyRoute,
FullSearchSchema,
NavigateOptions,
RegisteredRouter,
RouteApi,
RouteIds,
} from "@tanstack/react-router";
import { useNavigate } from "@tanstack/react-router";
import { useCallback } from "react";

type SearchParams<R extends AnyRoute> = FullSearchSchema<R>;

type SetSearchParams<R extends AnyRoute> = (
changes: Partial<SearchParams<R>>,
options?: Omit<NavigateOptions, "to" | "search">,
) => Promise<void>;

export function useSearchState<
TId extends RouteIds<RegisteredRouter["routeTree"]>,
TRoute extends AnyRoute,
>(
route: RouteApi<TId, TRoute>,
): [SearchParams<TRoute>, SetSearchParams<TRoute>] {
const navigate = useNavigate();
const search: SearchParams<TRoute> = route.useSearch();
const setSearch: SetSearchParams<TRoute> = useCallback(
(changes, options) =>
navigate({
to: route.id as string,
search: { ...search, ...changes },
...options
}),
[navigate, route.id, search],
);
return [search, setSearch];
}
This is how you would use it:
import { useNavigate } from "@tanstack/react-router";
import { useCallback } from "react";
import { useSearchState } from "./useSearchState";

const route = new RouteApi({ id: "/dashboard" });

export default function Dashboard() {
const [{ date }, setSearch] = useSearchState(route);
return (
<>
Input date: {date?.toString()}
<button onClick={() => setSearch({ date: new Date() }, {replace: true})}>
Update date
</button>
</>
);
import { useNavigate } from "@tanstack/react-router";
import { useCallback } from "react";
import { useSearchState } from "./useSearchState";

const route = new RouteApi({ id: "/dashboard" });

export default function Dashboard() {
const [{ date }, setSearch] = useSearchState(route);
return (
<>
Input date: {date?.toString()}
<button onClick={() => setSearch({ date: new Date() }, {replace: true})}>
Update date
</button>
</>
);
0 Replies
No replies yetBe the first to reply to this messageJoin

Did you find this page helpful?