Gathering detailed insights and metrics for react-magic-search-params
Gathering detailed insights and metrics for react-magic-search-params
Gathering detailed insights and metrics for react-magic-search-params
Gathering detailed insights and metrics for react-magic-search-params
Useful library to manage the parameters of any web application, thanks to autocompletion with typescript
npm install react-magic-search-params
Typescript
Module System
Min. Node Version
Node Version
NPM Version
66.7
Supply Chain
92.5
Quality
81.7
Maintenance
100
Vulnerability
100
License
TypeScript (98.73%)
JavaScript (1.27%)
Built with Next.js • Fully responsive • SEO optimized • Open source ready
Total Downloads
863
Last Day
1
Last Week
10
Last Month
43
Last Year
863
MIT License
4 Stars
8 Commits
1 Forks
1 Watchers
1 Branches
1 Contributors
Updated on Apr 26, 2025
Latest Version
1.2.0
Package Id
react-magic-search-params@1.2.0
Unpacked Size
145.94 kB
Size
33.02 kB
File Count
16
NPM Version
10.5.0
Node Version
20.15.1
Published on
Apr 26, 2025
Cumulative downloads
Total Downloads
Last Day
0%
1
Compared to previous day
Last Week
0%
10
Compared to previous week
Last Month
30.3%
43
Compared to previous month
Last Year
0%
863
Compared to previous year
react-magic-search-params
🪄 To install this library, run:
1npm install react-magic-search-params
Introducción General
1.1 Propósito del Hook
1.2 Contexto de Implementación
Tipos de Parámetros que Acepta
2.1 mandatory (Obligatorios)
2.2 optional (Opcionales)
2.3 defaultParams
2.4 forceParams
2.5 omitParamsByValues
2.6 arraySerialization
Funciones Principales
4.1 getParams
4.2 updateParams
4.3 clearParams
El hook useMagicSearchParams
habilita un manejo avanzado y centralizado de parámetros en la URL.
Permite definir y unificar lógica para filtrar, paginar o realizar cualquier otra operación que dependa de parámetros en la cadena de consulta (ej. ?page=1&page_size=10
).
Antes (sin autocompletado ni tipado)
En esta sección se ilustra rápidamente cómo cambiaba el manejo de parámetros antes de usar el hook y cómo se simplifica con useMagicSearchParams
.
1// filepath: /example/BeforeHook.tsx 2 3export const BeforeHookExample = () => { 4 const [searchParams, setSearchParams] = useSearchParams() 5 6 // Extraer valores manualmente (sin tipado ni validación) 7 const page = parseInt(searchParams.get('page') || '1', 10) 8 const pageSize = parseInt(searchParams.get('page_size') || '10', 10) 9 const search = searchParams.get('search') || '' 10 11 const handleChangePage = (newPage: number) => { 12 searchParams.set('page', newPage.toString()) 13 setSearchParams(searchParams) 14 } 15 16 return ( 17 <div> 18 <p>Página: {page}</p> 19 <p>page_size: {pageSize}</p> 20 <p>search: {search}</p> 21 {/* Botón para cambiar de página */} 22 <button onClick={() => handleChangePage(page + 1)}>Siguiente página</button> 23 </div> 24 ) 25}
1// filepath: /example/AfterHook.tsx 2import { useMagicSearchParams } from "react-magic-search-params"; 3import { paramsUsers } from "@/constants/DefaultParamsPage"; 4 5export const AfterHookExample = () => { 6 // contexto de Api externa... 7 const { searchParams, getParams, updateParams } = useMagicSearchParams({ 8 ...paramsUsers, 9 forceParams: { page_size: paramsUsers.mandatory.page_size }, // se limita a 10 10 omitParamsByValues: ["all", "default"], 11 }); 12 13 useEffect(() => { 14 const paramsUser = getParams(); 15 16 async function loadUsers() { 17 toast.loading("Cargando...", { id: "loading" }); 18 19 console.log({ paramsUser }); 20 const { success, message } = await getUsersContext(paramsUser); 21 if (success) { 22 toast.success(message ?? "Usuarios obtenidos", { id: "loading" }); 23 setLoading(false); 24 } else { 25 toast.error(message ?? "Error inesperado al obtener los usuarios", { 26 id: "loading", 27 }); 28 } 29 } 30 loadUsers(); 31 }, [searchParams]); 32 33 // getParams devuelve datos convertidos y tipados con autocompletado 34 const { page, page_size, search } = getParams({ convert: true }); 35 36 const handleNextPage = () => { 37 const nextPage = { page: (page ?? 1) + 1 }; 38 updateParams({ newParams: nextpage }); // por defecto se mantienen los otros parámetros de consulta 39 }; 40 41 return ( 42 <div> 43 {/* Nota: normalmente el input será de tipo "no controlado" debido a que normalmente se utilizar una técnica de "debounce" para demorar la actualización */} 44 <input 45 defaultValue={search} 46 placeholder="Buscar por..." 47 onChange={handleSearchChange} 48 /> 49 <p>Página actual: {page}</p> 50 <p>Tamaño de página: {page_size}</p> 51 <p>Búsqueda: {search}</p> 52 <button onClick={handleNextPage}>Siguiente página</button> 53 </div> 54 ); 55};
mandatory
y optional
.
Se evita duplicar lógica de extracción y validación de parámetros.?page=1&page_size=10
en vez de ?page_size=10&page=1
).filtros por defecto
o configuraciones iniciales.sistema/lista?page=1&page_size=10
, estos se cargan según el componente (página) que se este visitando, asegurando que la página visitada siempre tenga parámetros por defecto, aunque el usuario los elimine, esto asegura que las llamadas a una API que útiliza los párametros de la URL devuelva los datos correctos.getParams
para obtener sus valores de tipo string ej:tags=uno,dos,tres
o convertido a su tipo original ej: tags: ['uno', 'dos','tres']
[!NOTE] De esta forma Typescript Podrá inferir los tipos de los párametros de consulta y sus valores por defecto a manejar.
1type UserTagOptions = 'tag1' | 'tag2' | 'react' | 'node' | 'typescript' | 'javascript'; 2type OrderUserProps = 'role' | 'date'; 3// Puedes especificar los valores para ayudar a que typescript te de más tipado 4export const paramsCrimesDashboard = { 5 mandatory: { 6 days: 7, 7 }, 8 optional: {}, 9}; 10export const paramsUsers = { 11 mandatory: { 12 page: 1, 13 page_size: 10 as const, 14 only_is_active: false, 15 }, 16 optional: { 17 order: "", as OrderUserProps 18 search: "", 19 tags: ['tag1', 'tag2'] as Array<UserTagOptions> 20 }, 21};
[!TIP] Al declarar explícitamente los tipos (en lugar de basarse únicamente en la inferencia de tipos), se permite que TypeScript proporcione una comprobación de tipos más estricta. Esto garantiza que solo se permitan los valores definidos para cada parámetro, lo que ayuda a evitar la asignación accidental de valores no válidos.
Obtiene los parámetros tipados y opcionalmente convertidos desde la URL.
Útil para recuperar “page”, “order”, “search”, etc., sin lidiar con valores nulos o tipos incorrectos.
[!NOTE] Por defecto el hook
useSearchParams
de react-router-dom devuelve los parámetros enstring
, haunque los hayamos definido con otro tipo ej:number
, esto lo soluciona el metodogetParams
gracias a que guarda una referencia de su tipo original.
1// Obteniendo valores convertidos 2const { page, search } = getParams({ convert: true }); 3 4// Ejemplo: mostrar parámetros en consola 5console.log("Página actual:", page); // number 6console.log("Búsqueda:", search); // string | undefined
Modifica de forma controlada los parámetros en la URL, respetando valores obligatorios;
puedes reiniciar un valor sin perder el resto (ej. setear page=1
y mantener search
).
1// Cambiar de página y conservar orden actual 2updateParams({ 3 newParams: { page: 2 }, 4 keepParams: { order: true }, 5}); 6 7// Establecer un nuevo filtro y reiniciar la página 8updateParams({ newParams: { page: 1, search: "John" } });
Reinicia los parámetros de la URL, manteniendo (o no) los obligatorios. Permite “limpiar” los filtros y volver al estado inicial.
1// Limpia todo y conserva obligatorios 2clearParams(); 3 4// Limpia incluso los obligatorios 5clearParams({ keepMandatoryParams: false });
En el siguiente ejemplo, se combinan:
mandatory: Necesarios para la paginación. optional: Parámetros de búsqueda y orden. forceParams: Parámetros que no deben cambiar (p. ej. “page_size=1”). omitParamsByValues: Se omiten valores como “all” o “default”.
1// filepath: /c:/.../FilterUsers.tsx 2import { useMagicSearchParams } from "@/hooks/UseMagicSearchParams"; 3import { paramsUsers } from "@constants/DefaultParamsPage"; 4 5export const FilterUsers = (props) => { 6 const { searchParams, updateParams, clearParams, getParams } = 7 useMagicSearchParams({ 8 ...paramsUsers, 9 defaultParams: paramsUsers.mandatory, 10 forceParams: { page_size: 1 }, 11 omitParamsByValues: ["all", "default"], 12 }); 13 14 // Recuperar parámetros convertidos a sus tipos originales 15 const { page, search, order } = getParams({ convert: true }); 16 17 // Actualizar: setear página = 1 y cambiar búsqueda 18 const handleChangeSearch = (evt) => { 19 updateParams({ newParams: { page: 1, search: evt.target.value } }); 20 }; 21 22 // Limpiar todo y conservar mandatorios por defecto 23 const handleReset = () => { 24 clearParams(); 25 }; 26 27 // ... 28};
En este componente:
paramsUsers define los objetos “mandatory” y “optional”. forceParams evita que “pagesize” sea modificado por el usuario. **_omitParamsByValues** descarta valores que no aporten datos reales (“all”, “default”). getParams devuelve valores tipados (números, booleanos, strings, etc.). updateParams y **clearParams** simplifican los flujos de actualización en la URL.
El hook useMagicSearchParams
ahora permite gestionar parámetros de tipo array de forma avanzada y flexible, enviándolos de forma óptima al backend según el formato requerido. Esto se logra mediante la opción arraySerialization
, que admite tres técnicas:
csv:
Serializa el array en una única cadena separada por comas.
Ejemplo:
tags=tag1,tag2,tag3
Ideal cuando el backend espera un solo string.
repeat:
Envía cada elemento del array como un parámetro separado.
Ejemplo:
tags=tag1&tags=tag2&tags=tag3
Perfecto para APIs que manejan múltiples entradas con la misma clave.
brackets:
Utiliza la notación con corchetes en la clave para cada elemento.
Ejemplo:
tags[]=tag1&tags[]=tag2&tags[]=tag3
Útil para frameworks que esperan este formato (ej. PHP).
[!TIP] Al extraer los valores de
tags
congetParams({ convert: true })
obtendrás:
- String si no se especifica conversión (ej:csv):
"tags=tag1,tag2,tag3"
- Array si se convierte:
tags=['tag1', 'tag2', 'tag3']
Esto mejora la consistencia y tipado en tu aplicación.
Flexibilidad de Envío:
Elige el método que mejor se adapte a las necesidades del backend.
✅ Mayor compatibilidad con distintos sistemas.
Normalización Automática:
Las claves que llegan en formato tags[]
se normalizan a tags
para facilitar su manejo.
✅ Más fácil iterar y convertir a tipos originales.
Control Total de la URL:
El hook gestiona la reescritura de la URL de forma consistente, reduciendo errores y manteniendo la legibilidad.
🔒 Mejora la seguridad y el control de los parámetros.
1import { useMagicSearchParams } from "../src/hooks/useMagicSearchParams"; 2import { paramsUsers } from "../src/constants/defaulParamsPage"; 3 4export default function App() { 5 const { searchParams, getParams, updateParams, clearParams } = useMagicSearchParams({ 6 ...paramsUsers, 7 defaultParams: paramsUsers.mandatory, 8 arraySerialization: 'repeat', // Puedes cambiar a 'csv' o 'brackets' según prefieras. 9 omitParamsByValues: ["all", "default"], 10 }); 11 12 // Obtener parámetros convertidos (por ejemplo, tags se obtiene como array) 13 const { tags, page } = getParams({ convert: true }); 14 15 const availableTags = ['react', 'node', 'typescript', 'javascript'] 16 17 // Ejemplo: Actualizar el array de tags con toggle 18 const handleTagToggle = (newTag: string) => { 19 // si ya existe se elimina, sino se agrega 20 updateParams({ newParams: { tags: newTag } }); 21 }; 22 // pasar un array de tags, útil para agregar múltiples filtros a la vez 23 const handleTagToggleArray = (newTags: string[]) => { 24 // el hook se encarga de que no existán valores repetidos en el array haciendo 25 // merge con los anteriores 26 updateParams({ newParams: { tags: [...tags, ..newTags] } }); 27 }; 28 return ( 29 <div> 30 <div> 31 <h3 className='text-lg font-semibold mb-3'>Selecciona Tags:</h3> 32 {availableTags.map(tag => { 33 const isActive = Array.isArray(tags) && tags.includes(tag) 34 return ( 35 <button 36 key={tag} 37 onClick={() => handleTagToggle(tag)} 38 className={`px-4 py-2 rounded-md border ${ 39 isActive ? 'bg-blue-500 text-white' : 'bg-gray-200 text-gray-700' 40 }`} 41 > 42 {tag} 43 </button> 44 ) 45 })} 46 </div> 47 <p>Tags actuales: {JSON.stringify(tags)}</p> 48 {/* Resto del componente */} 49 </div> 50 ); 51}
En este ejemplo, al utilizar la serialización repeat, la URL
resultante se verá así:
?page=1&page_size=10&only_is_active=false&tags=tag1&tags=tag2&tags=tag3
?page=1&page_size=10&only_is_active=false&tags=tag1,tag2,tag3
?page=1&page_size=10&only_is_active=false&tags[]=tag1&tags[]=tag2&tags[]=tag3
Este proyecto cuenta con pruebas automatizadas para asegurar su robustez y fiabilidad.
Vitest
🧪Para validar el funcionamiento de este hook (y de los demás), puedes dirigirte al directorio de tests y ejecutar el siguiente comando en la terminal:
1npm run test ./test/useMagicSearchParams.test.ts
[!WARNING] Nota: Asegúrate de tener Vitest configurado en tu proyecto para que estas pruebas se ejecuten correctamente, puedes ver la versión con
npm list
El hook useMagicSearchParams
aporta:
Se recomienda ajustarlo o expandirlo según las necesidades de cada proyecto, añadiendo, por ejemplo, validaciones avanzadas o conversiones adicionales de tipos.
[!TIP] Puede encontrar ejemplos prácticos de cómo implementar este Hook en *proyectos grandes, en el archivo de ejemplo.
Si encontraste esta libreriá útil, porfavor dale una ⭐️ al GitHub!
General Introduction
1.1 Hook Purpose
1.2 Implementation Context
Accepted Parameter Types
2.1 mandatory (Required)
2.2 optional (Optional)
2.3 defaultParams
2.4 forceParams
2.5 omitParamsByValues
2.6 arraySerialization
Main Functions
4.1 getParams
4.2 updateParams
4.3 clearParams
The useMagicSearchParams
hook enables advanced and centralized management of URL parameters.
It allows you to define and unify logic to filter, paginate, or perform any other operation that depends on query parameters (e.g. ?page=1&page_size=10
).
Before (no autocomplete or typing)
This section quickly illustrates how parameter handling changed before using the hook and how it simplifies with useMagicSearchParams
.
1// filepath: /example/BeforeHook.tsx 2 3export const BeforeHookExample = () => { 4 const [searchParams, setSearchParams] = useSearchParams() 5 6 // Manually extract values (no typing or validation) 7 const page = parseInt(searchParams.get('page') || '1', 10) 8 const pageSize = parseInt(searchParams.get('page_size') || '10', 10) 9 const search = searchParams.get('search') || '' 10 11 const handleChangePage = (newPage: number) => { 12 searchParams.set('page', newPage.toString()) 13 setSearchParams(searchParams) 14 } 15 16 return ( 17 <div> 18 <p>Page: {page}</p> 19 <p>page_size: {pageSize}</p> 20 <p>search: {search}</p> 21 {/* Button to move to the next page */} 22 <button onClick={() => handleChangePage(page + 1)}>Next page</button> 23 </div> 24 ) 25}
1// filepath: /example/AfterHook.tsx 2import { useMagicSearchParams } from "react-magic-search-params"; 3import { paramsUsers } from "@/constants/DefaultParamsPage"; 4 5export const AfterHookExample = () => { 6 // context of an external API... 7 const { searchParams, getParams, updateParams } = useMagicSearchParams({ 8 ...paramsUsers, 9 forceParams: { page_size: paramsUsers.mandatory.page_size }, // limited to 10 10 omitParamsByValues: ["all", "default"], 11 }); 12 13 useEffect(() => { 14 const paramsUser = getParams(); 15 16 async function loadUsers() { 17 toast.loading("Loading...", { id: "loading" }); 18 19 console.log({ paramsUser }); 20 const { success, message } = await getUsersContext(paramsUser); 21 if (success) { 22 toast.success(message ?? "Users retrieved", { id: "loading" }); 23 setLoading(false); 24 } else { 25 toast.error(message ?? "Unexpected error retrieving the users", { 26 id: "loading", 27 }); 28 } 29 } 30 loadUsers(); 31 }, [searchParams]); 32 33 // getParams returns typed and converted data with autocomplete 34 const { page, page_size, search } = getParams({ convert: true }); 35 36 const tags = getParam("tags", { convert: false }) 37 38 const handleNextPage = () => { 39 const nextPage = { page: (page ?? 1) + 1 }; 40 updateParams({ newParams: nextPage }); // by default, the rest of the query parameters are preserved 41 }; 42 43 return ( 44 <div> 45 {/* Note: typically this input will be “uncontrolled,” as you often use a “debounce” approach to delay updates */} 46 <input 47 defaultValue={search} 48 placeholder="Search by..." 49 onChange={handleSearchChange} 50 /> 51 <p>Current page: {page}</p> 52 <p>Page size: {page_size}</p> 53 <p>Search: {search}</p> 54 <button onClick={handleNextPage}>Next page</button> 55 </div> 56 ); 57};
[!NOTE] Since this hook utilizes react-router-dom, make sure your application is wrapped in
<BrowserRouter>
or<RouterProvider>
(the modern version in React Router v6.4+) so that routing works correctly.
?page=1&page_size=10
en instead ?page_size=1000&page=1
).“default filters”
or initial settings.sistema/lista?page=1&page_size=10
, , these load depending on the component (page) being visited, ensuring that the visited page always has default parameters, even if the user removes them. This ensures that API calls depending on URL parameters return correct data.tags: [‘one’, ‘two’, ‘three’]
).[!NOTE] This way TypeScript can infer the types of the query parameters and their default values to manag
1type UserTagOptions = 'tag1' | 'tag2' | 'react' | 'node' | 'typescript' | 'javascript'; 2type OrderUserProps = 'role' | 'date'; 3// you can specify the values to help typescript give you more typed 4export const paramsCrimesDashboard = { 5 mandatory: { 6 days: 7, 7 }, 8 optional: {}, 9}; 10export const paramsUsers = { 11 mandatory: { 12 page: 1, 13 page_size: 10 as const, 14 only_is_active: false, 15 }, 16 optional: { 17 order: "" as OrderUserProps; 18 search: "", 19 tags: ['tag1', 'tag2'] as Array<UserTagOptions> 20 }, 21};
[!TIP] By explicitly declaring the types (instead of relying solely on type inference), you enable TypeScript to provide stricter type checking. This ensures that only the defined values are allowed for each parameter, helping to avoid accidental assignment of invalid values.
Retrieves typed parameters from the URL and optionally converts them.
Useful to pull “page”, “order”, “search”
, etc. without dealing with null values or incorrect types.
[!NOTE] By default, the react-router-dom
useSearchParams
hook returns parameters asstring
, even if defined with another type (e.g.number
). ThegetParams
method solves this by keeping a reference to their original type.
1// Retrieving converted values 2const { page, search } = getParams({ convert: true }); 3const tags = getParam("tags") 4// tags = [tag1, tag2] 5 6// Example: displaying parameters in console 7console.log("Current page:", page); // number 8console.log("Search:", search); // string | undefined
Safely modifies URL parameters, respecting mandatory values; you may reset one value without losing the rest (e.g. set page=1
while keeping search
).
1// Change page and keep the current order 2updateParams({ 3 newParams: { page: 2 }, 4 keepParams: { order: true }, 5}); 6 7// Set a new filter and reset the page 8updateParams({ newParams: { page: 1, search: "John" } });
Resets the URL parameters, optionally keeping mandatory ones. Allows you to “clear” the filters and return to the initial state.
1// Clear everything and keep mandatory parameters 2clearParams(); 3 4// Clear everything, including mandatory parameters 5clearParams({ keepMandatoryParams: false });
The onChange
function allows you to subscribe to changes in specific URL parameters. Each time the parameter changes, the associated callbacks will be executed. This is useful when you need to trigger updates or actions (such as API calls, validations, etc.) after a particular value changes.
[!NOTE] Although you will usually want to call an API or trigger other events as soon as changes are detected in any of the URL parameters (by adding
searchParams
to the dependency array ofuseEffect
), there are occasions where you may prefer more granular control and only react to specific parameters.
Basic use
1useEffect(() => { 2 function fetchData() { 3 4 // can be an call to API or any other operation 5 return new Promise((resolve) => { 6 setTimeout(() => resolve('Information recibed'), 1500) 7 }) 8 } 9 10 function showData(data: string) { 11 alert(`Data recibed: ${data}`) 12 } 13 14 function notifyChange() { 15 console.log('Change detected in the parameter search') 16 } 17 18 onChange('search', [ 19 async () => { 20 const data = await fetchData() 21 showData(data) 22 }, 23 notifyChange 24 ]) 25}, []) 26 // otr
In the following example, we combine:
mandatory: Needed for pagination.
optional: Search and order parameters.
forceParams: Parameters that must not change
omitParamsByValues: Omits all
or default
values.
1// filepath: /c:/.../FilterUsers.tsx 2import { useMagicSearchParams } from "@/hooks/UseMagicSearchParams"; 3import { paramsUsers } from "@constants/DefaultParamsPage"; 4 5export const FilterUsers = (props) => { 6 const { searchParams, updateParams, clearParams, getParams } = 7 useMagicSearchParams({ 8 ...paramsUsers, 9 defaultParams: paramsUsers.mandatory, 10 forceParams: { page_size: 1 }, 11 omitParamsByValues: ["all", "default"], 12 }); 13 14 // Retrieve parameters converted to their original types 15 const { page, search, order } = getParams({ convert: true }); 16 17 18 // Update: set page = 1 and change search 19 const handleChangeSearch = (evt) => { 20 updateParams({ newParams: { page: 1, search: evt.target.value } }); 21 }; 22 23 // Clear everything and keep mandatory parameters by default 24 const handleReset = () => { 25 clearParams(); 26 }; 27 const handleChangeOrder = (value) => { 28 // if value is equal to 'all' it will be ommited 29 updateParams({ newParams: { order: value }, keepParams: { search: false }}) 30 } 31 // ... 32 return ( 33 <> 34 {/** rest.. */} 35 <select name="order" onChange={e => handleChangeOrder(e)}> 36 <option value="all">Select tag</option> 37 38 {/** map of tags..*/} 39 </select> 40 41 </> 42 ) 43};
En este componente:
paramsUsers: defines the mandatory
and optional
objects.
forceParams: prevents “page*size” from being changed by the user.
_omitParamsByValues: discards values that do not provide real data (“all”, “default”)
getParams: returns typed values (numbers, booleans, strings, etc.).
updateParams and clearParams simplify URL update flows.
The useMagicSearchParams hook now allows for advanced and flexible handling of aarray-type parameters
, sending them to the backend
in the format required. This is done via the arraySerialization option, which supports three techniques:
csv:
Serializes the array into a single comma-separated string.
Ejemplo:
tags=tag1,tag2,tag3
Ideal when the backend expects a single string.
repeat:
Sends each array element as a separate parameter.
Ejemplo:
tags=tag1&tags=tag2&tags=tag3
Perfect for APIs that handle multiple entries under the same key.
brackets:
Uses bracket notation in the key for each element.
Ejemplo:
tags[]=tag1&tags[]=tag2&tags[]=tag3
Useful for frameworks expecting this format (e.g. PHP).
[!TIP] When extracting
tags
withgetParams({ convert: true })
you get:
- Am String if not conversion is specified (e.g, csv):
"tags=tag1,tag2,tag3"
- An Array if conversion is used:
tags=['tag1', 'tag2', 'tag3']
This improves consistency and typing in your application.
Flexible Submission:
Choose the method that best suits backend requirements.
✅ Better compatibility with various systems.
Automatic Normalization:
Keys arriving tags[]
format normalize to tags
to simplify handling.
✅ Easier iteration and conversion to original types.
Full URL Control:
The hook consistently manages URL rewriting, reducing errors and keeping it readable.
🔒 Improves parameter security and control.
1import { useMagicSearchParams } from "useMagicSearchParams"; 2import { paramsUsers } from "../src/constants/defaulParamsPage"; 3 4export default function App() { 5 const { searchParams, getParams, updateParams, clearParams } = useMagicSearchParams({ 6 ...paramsUsers, 7 defaultParams: paramsUsers.mandatory, 8 arraySerialization: 'repeat', // You can switch to 'csv' or 'brackets' as needed. 9 omitParamsByValues: ["all", "default"], 10 }); 11 12 // Get converted parameters (for example, tags is retrieved as an array) 13 const { tags, page } = getParams({ convert: true }); 14 15 const availableTags = ['react', 'node', 'typescript', 'javascript']; 16 17 // Example: Update the tags array with toggle 18 const handleTagToggle = (newTag: string) => { 19 // if it exists, remove it; otherwise, add it 20 updateParams({ newParams: { tags: newTag } }); 21 }; 22 23 // Pass an array of tags, useful for adding multiple filters at once 24 const handleTagToggleArray = (newTags: string[]) => { 25 // the hook ensures no duplicates by merging with existing ones 26 updateParams({ newParams: { tags: [...tags, ...newTags] } }); 27 }; 28 29 return ( 30 <div> 31 <div> 32 <h3 className='text-lg font-semibold mb-3'>Select Tags:</h3> 33 {availableTags.map(tag => { 34 const isActive = Array.isArray(tags) && tags.includes(tag); 35 return ( 36 <button 37 key={tag} 38 onClick={() => handleTagToggle(tag)} 39 className={`px-4 py-2 rounded-md border ${ 40 isActive ? 'bg-blue-500 text-white' : 'bg-gray-200 text-gray-700' 41 }`} 42 > 43 {tag} 44 </button> 45 ); 46 })} 47 </div> 48 <p>Current tags: {JSON.stringify(tags)}</p> 49 {/* Rest of the component */} 50 </div> 51 ); 52}
In this example, when using repeat serialization the URL
result look like this:
?page=1&page_size=10&only_is_active=false&tags=tag1&tags=tag2&tags=tag3
?page=1&page_size=10&only_is_active=false&tags=tag1,tag2,tag3
?page=1&page_size=10&only_is_active=false&tags[]=tag1&tags[]=tag2&tags[]=tag3
mandatory
and optional
to avoid mismatches.This project includes automated tests to ensure its robustness and reliability.
To validate this hook (and others), go to the test directory and run the following command in your terminal:
1npm run test ./test/useMagicSearchParams.test.ts
[!WARNING] Note: Make sure you have Vitest configured in your project so these tests can run correctly; you can check the version with
npm list
The useMagicSearchParams
hook provides:
It’s recommended to adjust or expand it based on each project’s needs, for example by adding advanced validations or additional type conversions.
[!TIP] You can find practical examples of how to implement these hooks, saving you hundreds of lines of code in *large projects, in the example file.
If you found this library helpful, please give it a ⭐️ on GitHub!
No vulnerabilities found.