From a975fbeea40e051e116359bb6543b40ccf5b4c9c Mon Sep 17 00:00:00 2001 From: taro-28 Date: Sat, 31 Aug 2024 01:12:37 +0900 Subject: [PATCH] Update README --- README.md | 128 +++---- .../tanstack-table-search-params/README.md | 332 ++++++++++++++---- 2 files changed, 306 insertions(+), 154 deletions(-) diff --git a/README.md b/README.md index 0199ed7..2855c36 100644 --- a/README.md +++ b/README.md @@ -13,64 +13,32 @@ React Hook for syncing [TanStack Table](https://github.com/TanStack/table) state https://github.com/user-attachments/assets/1f1b4a65-fdec-4a80-a5d5-783642befaa3 -# Usage +# Quick Start -## Installation +First, install the package. ```bash npm i tanstack-table-search-params ``` -## Basic - -- [Next.js(Pages Router)](#nextjspages-router) -- [Next.js(App Router)](#nextjsapp-router) -- [TanStack Router](#tanstack-router) - -### Next.js(Pages Router) - -- [demo](https://tanstack-table-search-params-next-pages-router-taro28s-projects.vercel.app/) -- [code](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/next-pages-router) +For example, if you are using Next.js (Pages Router), you can use the hook like this. ```tsx import { useReactTable } from "tanstack-table"; import { useRouter } from "next/router"; import { useTableSearchParams } from "tanstack-table-search-params"; -// 1. Pass router and get the state and onChanges from the hook const router = useRouter(); -const stateAndOnChanges = useTableSearchParams(router); -const table = useReactTable({ - // 2. Pass the state and onChanges to the table - ...stateAndOnChanges, - data, - columns, - getCoreRowModel: getCoreRowModel(), - getFilteredRowModel: getFilteredRowModel(), - getSortedRowModel: getSortedRowModel(), - // ... other options +// Get state and onChanges +const stateAndOnChanges = useTableSearchParams({ + query: router.query, + push: router.push, + pathname: router.pathname, }); -``` - -### Next.js(App Router) - -- [demo](https://tanstack-table-search-params-next-app-router-taro28s-projects.vercel.app/) -- [code](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/next-app-router) - -```tsx -import { useReactTable } from "tanstack-table"; -import { usePathname, useRouter, useSearchParams } from "next/navigation"; -import { useTableSearchParams } from "tanstack-table-search-params"; - -const push = useRouter().push; -const query = useSearchParams(); -const pathname = usePathname(); -// 1. Pass push and query and get the state and onChanges from the hook -const stateAndOnChanges = useTableSearchParams({ push, query, pathname }); const table = useReactTable({ - // 2. Pass the state and onChanges to the table + // Set state and onChanges ...stateAndOnChanges, data, columns, @@ -81,55 +49,33 @@ const table = useReactTable({ }); ``` -### TanStack Router +Here is the [demo](https://tanstack-table-search-params-next-pages-router-taro28s-projects.vercel.app/). -- [demo](https://tanstack-table-search-params-tanstack-router-taro28s-projects.vercel.app/) -- [code](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/tanstack-router) +Of course, you can use it with other routers. -```tsx -import { useReactTable } from "tanstack-table"; -import { useTableSearchParams } from "tanstack-table-search-params"; +Please refer to the examples below: -export const Route = createFileRoute("/")({ - component: Page, -}); - -// ... +- [Next.js(Pages Router)](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/next-pages-router/src/pages/index.tsx) +- [Next.js(App Router)](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/next-app-router/src/app/table.tsx) +- [TanStack Router](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/tanstack-router/src/routes/index.tsx) -const navigate = Route.useNavigate(); -const query = Route.useSearch(); +# How it works -// 1. Pass push and query and get the state and onChanges from the hook -const stateAndOnChanges = useTableSearchParams({ - push: (url) => { - const searchParams = new URLSearchParams(url.split("?")[1]); - navigate({ search: Object.fromEntries(searchParams.entries()) }); - }, - query, - pathname: Route.path, -}); +The `useTableSearchParams` hook primarily does the following two things: -const table = useReactTable({ - // 2. Pass the state and onChanges to the table - ...stateAndOnChanges, - data, - columns, - getCoreRowModel: getCoreRowModel(), - getFilteredRowModel: getFilteredRowModel(), - getSortedRowModel: getSortedRowModel(), - // ... other options -}); -``` +- Decodes the `query` (React state of the query parameters) and returns it as the `state` of Tanstack Table. +- Encodes the `state` as query parameters and returns the `push` function as a function such as `onChangeGlobalFilter`. -## Options +# Options - [Custom query param name](#custom-query-param-name) - [Custom encoder/decoder](#custom-encoderdecoder) - [Custom default value](#custom-default-value) +- [Debounce](#debounce) -### Custom query param name +## Custom query param name -Query parameter names can be customized. +You can customize a query parameter name. - [demo](https://tanstack-table-search-paramsexample-git-56132d-taro28s-projects.vercel.app/custom-param-name) - [code](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/next-pages-router/src/pages/custom-param-name.tsx) @@ -145,11 +91,11 @@ const stateAndOnChanges = useTableSearchParams(router, { }); ``` -### Custom default value +## Custom default value -Default values can be customized. +You can customize the default value of a query parameter. -"default value" means the value that is used as value of `state` when the query parameter is not present. +The "default value" is the value that is used as the `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) @@ -177,9 +123,9 @@ useEffect(() => { }, [router.replace]); ``` -### Custom encoder/decoder +## Custom encoder/decoder -Encoder and decoder can be customized. +You can customize the encoder/decoder for the query parameter. - [demo](https://tanstack-table-search-paramsexample-git-56132d-taro28s-projects.vercel.app/custom-encoder-decoder) - [code](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/next-pages-router/src/pages/custom-encoder-decoder.tsx) @@ -248,7 +194,7 @@ const stateAndOnChanges = useTableSearchParams(router, { }); ``` -### Debounce +## Debounce You can debounce the reflection of state changes in the query parameters. @@ -264,7 +210,7 @@ const stateAndOnChanges = useTableSearchParams(router, { }); ``` -## Supported +# Supported List of supported TanStack table states @@ -282,11 +228,17 @@ List of supported TanStack table states - [ ] rowPinning - [ ] rowSelection -## Roadmap +# Roadmap + +- [ ] Support other table states +- [ ] Disable specific state +- [ ] Add `onChangeXxxQuery` option + +# TODO -- [ ] support other table states -- [ ] disable specific state -- [ ] add examples for other routers +- [ ] Add examples for other routers +- [ ] Add e2e tests +- [ ] Add JSDoc # License diff --git a/packages/tanstack-table-search-params/README.md b/packages/tanstack-table-search-params/README.md index 0199ed7..049a3a8 100644 --- a/packages/tanstack-table-search-params/README.md +++ b/packages/tanstack-table-search-params/README.md @@ -13,36 +13,32 @@ React Hook for syncing [TanStack Table](https://github.com/TanStack/table) state https://github.com/user-attachments/assets/1f1b4a65-fdec-4a80-a5d5-783642befaa3 -# Usage +# Quick Start -## Installation +First, install the package. ```bash npm i tanstack-table-search-params ``` -## Basic - -- [Next.js(Pages Router)](#nextjspages-router) -- [Next.js(App Router)](#nextjsapp-router) -- [TanStack Router](#tanstack-router) - -### Next.js(Pages Router) - -- [demo](https://tanstack-table-search-params-next-pages-router-taro28s-projects.vercel.app/) -- [code](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/next-pages-router) +For example, if you are using Next.js (Pages Router), you can use the hook like this. ```tsx import { useReactTable } from "tanstack-table"; import { useRouter } from "next/router"; import { useTableSearchParams } from "tanstack-table-search-params"; -// 1. Pass router and get the state and onChanges from the hook const router = useRouter(); -const stateAndOnChanges = useTableSearchParams(router); + +// Get state and onChanges +const stateAndOnChanges = useTableSearchParams({ + query: router.query, + push: router.push, + pathname: router.pathname, +}); const table = useReactTable({ - // 2. Pass the state and onChanges to the table + // Set state and onChanges ...stateAndOnChanges, data, columns, @@ -53,64 +49,211 @@ const table = useReactTable({ }); ``` -### Next.js(App Router) +Here is the [demo](https://tanstack-table-search-params-next-pages-router-taro28s-projects.vercel.app/). + +Of course, you can use it with other routers. + +Please refer to the examples below: + +- [Next.js(Pages Router)](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/next-pages-router/src/pages/index.tsx) +- [Next.js(App Router)](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/next-app-router/src/app/table.tsx) +- [TanStack Router](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/tanstack-router/src/routes/index.tsx) + +# How it works + +The `useTableSearchParams` hook primarily does the following two things: + +- Decodes the `query` (React state of the query parameters) and returns it as the `state` of Tanstack Table. +- Encodes the `state` as query parameters and returns the `push` function as a function such as `onChangeGlobalFilter`. + +# Options -- [demo](https://tanstack-table-search-params-next-app-router-taro28s-projects.vercel.app/) -- [code](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/next-app-router) +- [Custom query param name](#custom-query-param-name) +- [Custom encoder/decoder](#custom-encoderdecoder) +- [Custom default value](#custom-default-value) +- [Debounce](#debounce) + +## Custom query param name + +You can customize a query parameter name. + +- [demo](https://tanstack-table-search-paramsexample-git-56132d-taro28s-projects.vercel.app/custom-param-name) +- [code](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/next-pages-router/src/pages/custom-param-name.tsx) ```tsx -import { useReactTable } from "tanstack-table"; -import { usePathname, useRouter, useSearchParams } from "next/navigation"; -import { useTableSearchParams } from "tanstack-table-search-params"; +const stateAndOnChanges = useTableSearchParams(router, { + paramNames: { + // Customize query parameter name by passing a string + globalFilter: "userTable-globalFilter", + // Add prefix by passing a function + sorting: (defaultParamName) => `userTable-${defaultParamName}`, + }, +}); +``` -const push = useRouter().push; -const query = useSearchParams(); -const pathname = usePathname(); -// 1. Pass push and query and get the state and onChanges from the hook -const stateAndOnChanges = useTableSearchParams({ push, query, pathname }); +## Custom default value -const table = useReactTable({ - // 2. Pass the state and onChanges to the table - ...stateAndOnChanges, - data, - columns, - getCoreRowModel: getCoreRowModel(), - getFilteredRowModel: getFilteredRowModel(), - getSortedRowModel: getSortedRowModel(), - // ... other options +You can customize the default value of a query parameter. + +The "default value" is the value that is used as the `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, { + defaultValues: { + // Sort by name in descending order when query parameter is not present + sorting: [{ id: "name", desc: true }], + }, }); ``` -### TanStack Router +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 + + Users +; + +// Add the query parameter after the transition +useEffect(() => { + router.replace({ query: { globalFilter: "foo" } }); +}, [router.replace]); +``` + +## Custom encoder/decoder -- [demo](https://tanstack-table-search-params-tanstack-router-taro28s-projects.vercel.app/) -- [code](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/tanstack-router) +You can customize the encoder/decoder for the query parameter. + +- [demo](https://tanstack-table-search-paramsexample-git-56132d-taro28s-projects.vercel.app/custom-encoder-decoder) +- [code](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/next-pages-router/src/pages/custom-encoder-decoder.tsx) ```tsx -import { useReactTable } from "tanstack-table"; -import { useTableSearchParams } from "tanstack-table-search-params"; +const stateAndOnChanges = useTableSearchParams(router, { + // Use JSON.stringify/JSON.parse for encoding/decoding + encoders: { + // foo -> { "globalFilter": "foo" } + globalFilter: (globalFilter) => ({ + globalFilter: JSON.stringify(globalFilter), + }), + }, + decoders: { + // { "globalFilter": "foo" } -> foo + globalFilter: (query) => + query["globalFilter"] + ? JSON.parse(query["globalFilter"] as string) + : (query["globalFilter"] ?? ""), + }, +}); + +// ... -export const Route = createFileRoute("/")({ - component: Page, +const stateAndOnChanges = useTableSearchParams(router, { + // Encoders/decoders with different query parameter names can also be used. + encoders: { + // [{ id: "name", desc: true }] -> { "userTable-sorting": "[{ \"id\": \"name\", \"desc\": true }]" } + sorting: (sorting) => ({ + "userTable-sorting": JSON.stringify(sorting), + }), + }, + decoders: { + // { "userTable-sorting": "[{ \"id\": \"name\", \"desc\": true }]" } -> [{ id: "name", desc: true }] + sorting: (query) => + query["userTable-sorting"] + ? JSON.parse(query["userTable-sorting"] as string) + : query["userTable-sorting"], + }, }); // ... -const navigate = Route.useNavigate(); -const query = Route.useSearch(); +const stateAndOnChanges = useTableSearchParams(router, { + // Encoders/decoders with different numbers of query parameters can also be used. + encoders: { + // [{ id: "name", value: "foo" }] -> { "columnFilters.name": "\"foo\"" } + columnFilters: (columnFilters) => + Object.fromEntries( + columnFilters.map(({ id, value }) => [ + `columnFilters.${id}`, + JSON.stringify(value), + ]), + ), + }, + decoders: { + // { "columnFilters.name": "\"foo\"" } -> [{ id: "name", value: "foo" }] + columnFilters: (query) => + Object.entries(query) + .filter(([key]) => key.startsWith("columnFilters.")) + .map(([key, value]) => ({ + id: key.replace("columnFilters.", ""), + value: JSON.parse(value as string), + })), + }, +}); +``` + +## Debounce -// 1. Pass push and query and get the state and onChanges from the hook -const stateAndOnChanges = useTableSearchParams({ - push: (url) => { - const searchParams = new URLSearchParams(url.split("?")[1]); - navigate({ search: Object.fromEntries(searchParams.entries()) }); +You can debounce the reflection of state changes in the query parameters. + +- [demo](https://tanstack-table-search-paramsexample-git-56132d-taro28s-projects.vercel.app/debounce) +- [code](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/next-pages-router/src/pages/debounce.tsx) + +```tsx +const stateAndOnChanges = useTableSearchParams(router, { + debounceMilliseconds: { + // Debounce globalFilter by 500 milliseconds + globalFilter: 500, }, - query, - pathname: Route.path, +}); +``` + +# Supported + +List of supported TanStack table states +a# TanStack Table Search Params + +
+ +[![NPM Version](https://img.shields.io/npm/v/tanstack-table-search-params)][1] +[![NPM Downloads](https://img.shields.io/npm/dm/tanstack-table-search-params)][1] +[![GitHub Repo stars](https://img.shields.io/github/stars/taro-28/tanstack-table-search-params)][2] +[![Bundlephobia Minzipped size](https://img.shields.io/bundlephobia/minzip/tanstack-table-search-params)][3] + +
+ +React Hook for syncing [TanStack Table](https://github.com/TanStack/table) state with URL search params. + +https://github.com/user-attachments/assets/1f1b4a65-fdec-4a80-a5d5-783642befaa3 + +# Quick Start + +First, install the package. + +```bash +npm i tanstack-table-search-params +``` + +For example, if you are using Next.js (Pages Router), you can use the hook like this. + +```tsx +import { useReactTable } from "tanstack-table"; +import { useRouter } from "next/router"; +import { useTableSearchParams } from "tanstack-table-search-params"; + +const router = useRouter(); + +// Get state and onChanges +const stateAndOnChanges = useTableSearchParams({ + query: router.query, + push: router.push, + pathname: router.pathname, }); const table = useReactTable({ - // 2. Pass the state and onChanges to the table + // Set state and onChanges ...stateAndOnChanges, data, columns, @@ -121,15 +264,33 @@ const table = useReactTable({ }); ``` -## Options +Here is the [demo](https://tanstack-table-search-params-next-pages-router-taro28s-projects.vercel.app/). + +Of course, you can use it with other routers. + +Please refer to the examples below: + +- [Next.js(Pages Router)](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/next-pages-router/src/pages/index.tsx) +- [Next.js(App Router)](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/next-app-router/src/app/table.tsx) +- [TanStack Router](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/tanstack-router/src/routes/index.tsx) + +# How it works + +The `useTableSearchParams` hook primarily does the following two things: + +- Decodes the `query` (React state of the query parameters) and returns it as the `state` of Tanstack Table. +- Encodes the `state` as query parameters and returns the `push` function as a function such as `onChangeGlobalFilter`. + +# Options - [Custom query param name](#custom-query-param-name) - [Custom encoder/decoder](#custom-encoderdecoder) - [Custom default value](#custom-default-value) +- [Debounce](#debounce) -### Custom query param name +## Custom query param name -Query parameter names can be customized. +You can customize a query parameter name. - [demo](https://tanstack-table-search-paramsexample-git-56132d-taro28s-projects.vercel.app/custom-param-name) - [code](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/next-pages-router/src/pages/custom-param-name.tsx) @@ -145,11 +306,11 @@ const stateAndOnChanges = useTableSearchParams(router, { }); ``` -### Custom default value +## Custom default value -Default values can be customized. +You can customize the default value of a query parameter. -"default value" means the value that is used as value of `state` when the query parameter is not present. +The "default value" is the value that is used as the `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) @@ -177,9 +338,9 @@ useEffect(() => { }, [router.replace]); ``` -### Custom encoder/decoder +## Custom encoder/decoder -Encoder and decoder can be customized. +You can customize the encoder/decoder for the query parameter. - [demo](https://tanstack-table-search-paramsexample-git-56132d-taro28s-projects.vercel.app/custom-encoder-decoder) - [code](https://github.com/taro-28/tanstack-table-search-params/tree/main/examples/next-pages-router/src/pages/custom-encoder-decoder.tsx) @@ -248,7 +409,7 @@ const stateAndOnChanges = useTableSearchParams(router, { }); ``` -### Debounce +## Debounce You can debounce the reflection of state changes in the query parameters. @@ -264,7 +425,7 @@ const stateAndOnChanges = useTableSearchParams(router, { }); ``` -## Supported +# Supported List of supported TanStack table states @@ -282,11 +443,50 @@ List of supported TanStack table states - [ ] rowPinning - [ ] rowSelection -## Roadmap +# Roadmap + +- [ ] Support other table states +- [ ] Disable specific state +- [ ] Add `onChangeXxxQuery` option + +# TODO + +- [ ] Add examples for other routers +- [ ] Add e2e tests +- [ ] Add JSDoc + +# License + +MIT + +[1]: https://www.npmjs.com/package/tanstack-table-search-params +[2]: https://github.com/taro-28/tanstack-table-search-params +[3]: https://bundlephobia.com/package/tanstack-table-search-params + +- [x] globalFilter +- [x] sorting +- [x] pagination +- [x] columnFilters +- [ ] columnOrder +- [ ] columnPinning +- [ ] columnSizing +- [ ] columnSizingInfo +- [ ] columnVisibility +- [ ] expanded +- [ ] grouping +- [ ] rowPinning +- [ ] rowSelection + +# Roadmap + +- [ ] Support other table states +- [ ] Disable specific state + +# TODO -- [ ] support other table states -- [ ] disable specific state -- [ ] add examples for other routers +- [ ] Add examples for other routers +- [ ] Add e2e tests +- [ ] Add JSDoc # License