Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support default value option #43

Merged
merged 13 commits into from
Aug 28, 2024
37 changes: 36 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ const table = useReactTable({

## Advanced

- [Custom query param name](#custom-query-param-name)
- [Custom encoder/decoder](#custom-encoderdecoder)
- [Custom default value](#custom-default-value)

### Custom query param name

Query parameter names can be customized.
Expand Down Expand Up @@ -199,6 +203,38 @@ const stateAndOnChanges = useTableSearchParams(router, {
});
```

### Custom default value

Default values can be customized.

"default value" means the value that is used as value of `state` when the query parameter is not present.

- [demo](https://tanstack-table-search-paramsexample-git-56132d-taro28s-projects.vercel.app/custom-default-value)
- [code](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/next-pages-router/src/pages/custom-default-value.tsx)

```tsx
const stateAndOnChanges = useTableSearchParams(router, {
sorting: {
// Sort by name in descending order when query parameter is not present
defaultValue: [{ id: "name", desc: true }],
},
});
```

If you want to set initial values for query parameters, either transition with the query parameter or add the query parameter after the transition, depending on the router you are using.

```tsx
// Transition with the query parameter
<Link href={{ pathname: "/users", query: { globalFilter: "foo" } }}>
Users
</Link>;

// Add the query parameter after the transition
useEffect(() => {
router.replace({ query: { globalFilter: "foo" } });
}, [router.replace]);
```

## Supported

List of supported TanStack table states
Expand All @@ -219,7 +255,6 @@ List of supported TanStack table states

## TODO

- [ ] initial state
- [ ] disable specific state

# License
Expand Down
13 changes: 13 additions & 0 deletions examples/next-app-router/src/app/custom-default-value/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Suspense } from "react";
import { Table } from "./table";

export default function Page() {
return (
<main className="space-y-2 mx-6">
<h1 className="text-lg font-semibold">Custom default value</h1>
<Suspense>
<Table />
</Suspense>
</main>
);
}
43 changes: 43 additions & 0 deletions examples/next-app-router/src/app/custom-default-value/table.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"use client";

import { UserTable } from "@examples/lib/src/components/UserTable";
import {
useUserData,
userColumns,
} from "@examples/lib/src/components/userData";
import {
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import { useRouter, useSearchParams } from "next/navigation";
import { useTableSearchParams } from "tanstack-table-search-params";

export const Table = () => {
const data = useUserData();

const push = useRouter().push;
const query = useSearchParams();

const router = { push, query };

const stateAndOnChanges = useTableSearchParams(router, {
globalFilter: { defaultValue: "a" },
sorting: { defaultValue: [{ id: "name", desc: true }] },
pagination: { defaultValue: { pageIndex: 2, pageSize: 20 } },
columnFilters: { defaultValue: [{ id: "name", value: "b" }] },
});

const table = useReactTable({
data,
columns: userColumns,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getPaginationRowModel: getPaginationRowModel(),
...stateAndOnChanges,
});
return <UserTable table={table} />;
};
52 changes: 31 additions & 21 deletions examples/next-app-router/src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,30 @@ import Link from "next/link";
import type { ReactNode } from "react";
import "./globals.css";

type Menu = {
title: string;
href: string;
};

const menus = [
{
title: "Basic",
href: "/",
},
{
title: "Custom query param name",
href: "/custom-param-name",
},
{
title: "Custom encoder/decoder",
href: "/custom-encoder-decoder",
},
{
title: "Custom default value",
href: "/custom-default-value",
},
] as const satisfies Menu[];

export default function RootLayout({
children,
}: Readonly<{
Expand All @@ -16,27 +40,13 @@ export default function RootLayout({
</Link>
<nav>
<ul className="flex items-center">
<li>
<Link href="/" className="hover:text-gray-500 p-2">
Basic
</Link>
</li>
<li>
<Link
href="/custom-param-name"
className="hover:text-gray-500 p-2"
>
Custom query param name
</Link>
</li>
<li>
<Link
href="/custom-encoder-decoder"
className="hover:text-gray-500 p-2"
>
Custom encoder/decoder
</Link>
</li>
{menus.map((menu) => (
<li key={menu.href}>
<Link href={menu.href} className="hover:text-gray-500 p-2">
{menu.title}
</Link>
</li>
))}
</ul>
</nav>
</header>
Expand Down
52 changes: 31 additions & 21 deletions examples/next-pages-router/src/pages/_document.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,30 @@
import { Head, Html, Main, NextScript } from "next/document";
import Link from "next/link";

type Menu = {
title: string;
href: string;
};

const menus = [
{
title: "Basic",
href: "/",
},
{
title: "Custom query param name",
href: "/custom-param-name",
},
{
title: "Custom encoder/decoder",
href: "/custom-encoder-decoder",
},
{
title: "Custom default value",
href: "/custom-default-value",
},
] as const satisfies Menu[];

export default function Document() {
return (
<Html lang="en">
Expand All @@ -12,27 +36,13 @@ export default function Document() {
</Link>
<nav>
<ul className="flex items-center">
<li>
<Link href="/" className="hover:text-gray-500 p-2">
Basic
</Link>
</li>
<li>
<Link
href="/custom-param-name"
className="hover:text-gray-500 p-2"
>
Custom query param name
</Link>
</li>
<li>
<Link
href="/custom-encoder-decoder"
className="hover:text-gray-500 p-2"
>
Custom encoder/decoder
</Link>
</li>
{menus.map((menu) => (
<li key={menu.href}>
<Link href={menu.href} className="hover:text-gray-500 p-2">
{menu.title}
</Link>
</li>
))}
</ul>
</nav>
</header>
Expand Down
43 changes: 43 additions & 0 deletions examples/next-pages-router/src/pages/custom-default-value.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { UserTable } from "@examples/lib/src/components/UserTable";
import {
useUserData,
userColumns,
} from "@examples/lib/src/components/userData";
import {
getCoreRowModel,
getFilteredRowModel,
getPaginationRowModel,
getSortedRowModel,
useReactTable,
} from "@tanstack/react-table";
import { useRouter } from "next/router";
import { useTableSearchParams } from "tanstack-table-search-params";

export default function CustomParamNames() {
const data = useUserData();

const router = useRouter();
const stateAndOnChanges = useTableSearchParams(router, {
globalFilter: { defaultValue: "a" },
sorting: { defaultValue: [{ id: "name", desc: true }] },
pagination: { defaultValue: { pageIndex: 2, pageSize: 20 } },
columnFilters: { defaultValue: [{ id: "name", value: "b" }] },
});

const table = useReactTable({
data,
columns: userColumns,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
getFilteredRowModel: getFilteredRowModel(),
getPaginationRowModel: getPaginationRowModel(),
...stateAndOnChanges,
});

return (
<div className="space-y-2 mx-6">
<h1 className="text-lg font-semibold">Custom default value</h1>
<UserTable table={table} />
</div>
);
}
18 changes: 18 additions & 0 deletions examples/tanstack-router/src/routeTree.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import { Route as rootRoute } from './routes/__root'
import { Route as CustomParamNameImport } from './routes/custom-param-name'
import { Route as CustomEncoderDecoderImport } from './routes/custom-encoder-decoder'
import { Route as CustomDefaultValueImport } from './routes/custom-default-value'
import { Route as IndexImport } from './routes/index'

// Create/Update Routes
Expand All @@ -27,6 +28,11 @@ const CustomEncoderDecoderRoute = CustomEncoderDecoderImport.update({
getParentRoute: () => rootRoute,
} as any)

const CustomDefaultValueRoute = CustomDefaultValueImport.update({
path: '/custom-default-value',
getParentRoute: () => rootRoute,
} as any)

const IndexRoute = IndexImport.update({
path: '/',
getParentRoute: () => rootRoute,
Expand All @@ -43,6 +49,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof IndexImport
parentRoute: typeof rootRoute
}
'/custom-default-value': {
id: '/custom-default-value'
path: '/custom-default-value'
fullPath: '/custom-default-value'
preLoaderRoute: typeof CustomDefaultValueImport
parentRoute: typeof rootRoute
}
'/custom-encoder-decoder': {
id: '/custom-encoder-decoder'
path: '/custom-encoder-decoder'
Expand All @@ -64,6 +77,7 @@ declare module '@tanstack/react-router' {

export const routeTree = rootRoute.addChildren({
IndexRoute,
CustomDefaultValueRoute,
CustomEncoderDecoderRoute,
CustomParamNameRoute,
})
Expand All @@ -77,13 +91,17 @@ export const routeTree = rootRoute.addChildren({
"filePath": "__root.tsx",
"children": [
"/",
"/custom-default-value",
"/custom-encoder-decoder",
"/custom-param-name"
]
},
"/": {
"filePath": "index.tsx"
},
"/custom-default-value": {
"filePath": "custom-default-value.tsx"
},
"/custom-encoder-decoder": {
"filePath": "custom-encoder-decoder.tsx"
},
Expand Down
Loading