rudyhuynh / use-url-search-params Goto Github PK
View Code? Open in Web Editor NEWA React Hook to use URL query string as a state management
License: MIT License
A React Hook to use URL query string as a state management
License: MIT License
Hi,
recently I have started using this very useful hook but found a strange behavior when using the browser's back button.
When you modify your params
state several times and then you try to navigate back using the browser back button, only every second attempt is correct, I mean reflected in the application.
I created a simple demo to show the behavior https://codesandbox.io/s/delicate-lake-8todi?file=/src/App.js:915-932.
Steps to reproduce:
You have to click twice to navigate back to previous phrase / state of URL.
Is this intention?
Here is a Typescript wrapper around this package I write for my project (with a very good type-inference). The API has changed a little bit (initial
and types
are now combined into 1 param called initialOrType
for more concise syntax).
const [params, setParams] = useUrlSearchParams({ name: 'loi', age: Number, handsome: true }); // see value ('loi') and type (Number) are mixed
Now, the initial URLSearchParams is ?name=loi&handsome=true
, with the type of params
to be
{
name?: string,
age?: number,
handsome?: boolean
}
type Params = { name:'loi' | 'Loi', age: number, handsome: true }
const [params, setParams] = useUrlSearchParams({ name: 'loi', age: 21, handsome: true } as Params);
Now the type of params
becomes
{
name?: 'loi' | 'Loi' /* instead of string */,
age?: number,
handsome?: true /* instead of boolean */
}
const [params, setParams] = useUrlSearchParams({
name: 'loi' as 'loi | 'Loi',
age: Number,
handsome: true as true
});
will result in the same type as the example above.
(I will update immediately here if there's any bug)
useUrlSearchParams.ts
import { useUrlSearchParams as useOriginal } from 'use-url-search-params';
/**
* mix of Constructor and initial params
* e.g: TProps { a: '1', b: Number } will result to:
* - type typescript of { a: string, b: number }
* - type check (second param of useOriginal) of { a: String, b: Number }
* - initial params of { a: '1' } or ?a=1
*/
type TProps = Readonly<{
[key: string]:
| NumberConstructor
| StringConstructor
| BooleanConstructor
| DateConstructor
| number
| string
| boolean
| Date;
// See all the types supported by use-url-search-params here:
// https://github.com/rudyhuynh/use-url-search-params/blob/95b0880bf9e2bf84e19c779b2a4078a47271ea9c/src/useUrlSearchParams.js#L4
}>;
/**
* Convert from TProps to typescript type of the params
* e.g: TProps { a: '1', b: Number } will result to:
* { a: string, b: number }
*/
type GetUrlSearchParams<T extends TProps> = {
// We have the ? (optional) here because URLSearchParams is an external thing, so we cannot control whether it is presented as we expected it to be
[K in keyof T]?: T[K] extends NumberConstructor
? number
: T[K] extends StringConstructor
? string
: T[K] extends BooleanConstructor
? boolean
: T[K] extends DateConstructor
? Date
: T[K];
};
/**
*
* @param value mixed of initial param values and Constructors
* @returns whether the "value" is just a value, not a Constructor
* e.g: '1' => true, Number => false, String => false
*/
const isNotConstructor = (
value: TProps[string],
): value is string | number | boolean | Date =>
typeof value === 'string' ||
typeof value === 'number' ||
typeof value === 'boolean' ||
value instanceof Date;
/**
* wrapper around the original "useUrlSearchParams":
* https://github.com/rudyhuynh/use-url-search-params
*/
export function useUrlSearchParams<Props extends TProps>(initialOrType: Props) {
// exptract "initial" from "initialOrType"
// desired result: { param1: 'value1', param2: 123456 }
const initParams = Object.fromEntries(
// Learn the Object.fromEntries/Object.entries combination here:
// https://stackoverflow.com/a/14810722/9787887
Object.entries(initialOrType).filter(([_, value]) =>
isNotConstructor(value),
),
);
// exptract "type" from "initialOrType"
// desired result: { param1: String, param2: Number }
const paramsTypes = Object.fromEntries(
Object.entries(initialOrType).map(([key, value]) => [
key,
isNotConstructor(value) ? value.constructor : value,
]),
);
const [params, setParams] = useOriginal(initParams, paramsTypes);
// The setParams will add params to current params, NOT flush out all current params
// E.g: ?a=1&b=2, setParams({a:3}) will result in ?a=3&b=2
// look at its implementation here:
// https://github.com/rudyhuynh/use-url-search-params/blob/95b0880bf9e2bf84e19c779b2a4078a47271ea9c/src/useUrlSearchParams.js#L11
return [params, setParams] as unknown as [
GetUrlSearchParams<Props>,
(newParams: GetUrlSearchParams<Props>) => void,
];
}
would be nice to inform whether this hook runs in SSR or not.
First of all, thank you for creating this library! It looks quite nice.
Can you just add a support for Date
out of the box? I know I could write a custom resolver function, but this being a native JS primitive I think it deserves to be supported without manualy resolvers.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.