use-query-params

repository·master·Indexed 25 days ago

https://github.com/pbeshai/use-query-params

A React utility and library for synchronizing application state with URL query parameters. It includes the use-query-params hook for React and the serialize-query-params library for automatic serialization and deserialization of complex data types such as arrays, objects, dates, and enums. It supports custom parameter types and provides adapters for routing libraries like React Router 6.

Tokens
13K
Snippets
23
Records
73
Agent score
80%

What's inside use-query-params

  1. What is useQueryParams?

    master

    useQueryParams is a React solution for managing application state within URL query parameters. It provides a React Hook, Higher-Order Component (HOC), and Render Props pattern to handle the encoding and decoding of data.

    Key features include:

    • Easy Serialization: Automatically encodes and decodes data of any type (since URL parameters are natively strings) using the serialize-query-params library.
    • Smart Memoization: Prevents unnecessary re-renders and duplicate object creation.
    • Router Support: Works out of the box with React Router 5 and 6.
    • TypeScript Support: Fully typed for developer productivity.
  2. Define custom parameter types

    master

    You can define custom parameter types by creating an object with encode and decode functions. The library provides several built-in types and utility functions to assist with this.

    Built-in Param Types Behavior

    valueencodingdescription
    null?fooEncoded as a key with no value
    ""?foo=Encoded as an empty string
    undefined?Removed from the URL

    Common Built-in Types

    ParamTypeExample DecodedExample Encoded
    StringParamstring'foo'?qp=foo
    NumberParamnumber123?qp=123
    ObjectParam{ key: string }{ foo: 'bar', baz: 'zzz' }?qp=foo-bar_baz-zzz
    ArrayParamstring[]['a','b','c']?qp=a&qp=b&qp=c
    JsonParamany{ foo: 'bar' }?qp=%7B%22foo%22%3A%22bar%22%7D
    DateParamDateDate(2019, 2, 1)?qp=2019-03-01
    DateTimeParamDateDate(2019, 2, 1)?qp=2019-02-28T22:00:00.000Z
    BooleanParambooleantrue?qp=1
    NumericObjectParam{ key: number }{ foo: 1, bar: 2 }?qp=foo-1_bar-2
    DelimitedArrayParamstring[]['a','b','c']?qp=a_b_c
    DelimitedNumericArrayParamnumber[][1, 2, 3]?qp=1_2_3

    Enum Parameters

    Use createEnumParam for single values or createEnumArrayParam / createEnumDelimitedArrayParam for arrays to restrict decoded output to a specific list of allowed values.

    import { createEnumParam, createEnumArrayParam } from 'serialize-query-params';
    
    // String enum: values other than 'asc' or 'desc' decode as undefined
    const SortOrderEnumParam = createEnumParam(['asc', 'desc']);
    
    type Color = 'red' | 'green' | 'blue';
    // Array enum: values other than allowed colors decode as undefined
    const ColorArrayEnumParam = createEnumArrayParam<Color[]>(['red', 'green', 'blue']);
    import {
      encodeDelimitedArray,
      decodeDelimitedArray
    } from 'serialize-query-params';
    
    /** Uses a comma to delimit entries. e.g. ['a', 'b'] => qp?=a,b */
    const CommaArrayParam = {
      encode: (array: string[] | null | undefined): string | undefined => 
        encodeDelimitedArray(array, ','),
    
      decode: (arrayStr: string | string[] | null | undefined): string[] | undefined => 
        decodeDelimitedArray(arrayStr, ',')
    };
  3. Understand UrlUpdateType for URL updates

    master

    When calling setter functions from useQueryParam or useQueryParams, you can specify how the URL should be updated using the UrlUpdateType string. This determines whether the update affects only one parameter or the entire set, and whether it uses pushState or replaceState in the browser history.

    • 'pushIn': (Default) Push just a single parameter, leaving the rest as is. The back button works.
    • 'push': Push all parameters with just those specified. The back button works.
    • 'replaceIn': Replace just a single parameter, leaving the rest as is.
    • 'replace': Replace all parameters with just those specified.
  4. Set up the development environment

    master

    To run the project locally for development, follow these steps:

    1. Install dependencies:
      npm install
    2. Bootstrap the core packages:
      npx lerna bootstrap --hoist --scope "use-query-params" --scope "serialize-query-params"
    3. Build and test:
      npm build
      npm test
    npm install
    npx lerna bootstrap --hoist --scope "use-query-params" --scope "serialize-query-params"
    npm build
    npm test
  5. Install serialize-query-params via npm

    master

    Install the library using npm to simplify encoding and decoding URL query parameters.

    $ npm install --save serialize-query-params

    Note on URLSearchParams: By default, the library uses the browser's URLSearchParams API. This means it does not decode null and has limited handling for advanced URL configurations. For more advanced features, you can provide functions from third-party libraries like query-string to updateLocation and updateInLocation.

  6. Run local examples

    master

    To run the provided examples (like the React Router examples) locally, use the following commands:

    1. Bootstrap the example packages and link them:
      lerna bootstrap --scope "*-example"
      lerna link
    2. Start a specific example (e.g., the react-router-example):
       ```bash
    lerna run --scope react-router-example start
    lerna bootstrap --scope "*-example"
    lerna link
    lerna run --scope react-router-example start
  7. Install local versions of use-query-params and serialize-query-params using yalc

    master

    Because of potential React version mismatches when using npm link, this project uses yalc to manage local dependencies. To use the local versions of use-query-params and serialize-query-params in the React Router 6 example project, follow these steps:

    1. Build the core package from the repository root.
    2. Publish the packages to the local yalc store using the --no-scripts flag to avoid issues with hoisted dependencies.
    3. Add the published packages to the example project.

    Note: This workflow is specific to developers working with the local source code of the repository.

  8. Install use-query-params and set up QueryParamProvider

    master

    To use use-query-params, you must first install the package and wrap your application in a QueryParamProvider. The provider requires an adapter corresponding to your routing library (e.g., ReactRouter6Adapter for React Router 6).

    Basic Setup with React Router 6

    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import { QueryParamProvider } from 'use-query-params';
    import { ReactRouter6Adapter } from 'use-query-params/adapters/react-router-6';
    import { BrowserRouter, Route, Routes } from 'react-router-dom';
    import App from './App';
    
    const root = ReactDOM.createRoot(
      document.getElementById('root') as HTMLElement
    );
    root.render(
      <BrowserRouter>
        <QueryParamProvider adapter={ReactRouter6Adapter}>
          <Routes>
            <Route path="/" element={<App />}>
          </Routes>
        </QueryParamProvider>
      </BrowserRouter>,
      document.getElementById('root')
    );

    Advanced Setup with query-string

    By default, the library uses URLSearchParams, which has limited handling for null and advanced configurations. For more robust parsing/stringifying, you can provide parse and stringify functions from the query-string library via the options prop:

    import { parse, stringify } from 'query-string';
    // ... other imports
    
    <QueryParamProvider 
      adapter={ReactRouter6Adapter}
      options={{
        searchStringToObject: parse,
        objectToSearchString: stringify,
      }}
    >
      <Routes>
        <Route path="/" element={<App />}>
      </Routes>
    </QueryParamProvider>
  9. Understand the type mappings for QueryParamConfigMap

    master

    When you define a QueryParamConfigMap, several utility types can be used to derive the types of your parameters at different stages of the serialization lifecycle:

    • DecodedValueMap<QPCMap>: Represents the types of the values after they have been decoded from the URL (the return type of the decode function).
    • EncodedValueMap<QPCMap>: Represents the types of the values as they exist in the URL (the EncodedValue type).
    • ToBeEncodedValueMap<QPCMap>: Represents the types of the values that need to be passed to the encode function (the first argument of the encode function).
  10. Configure QueryParamProvider options

    master

    The QueryParamProvider accepts an options object to configure global behavior for all hooks and components using the provider.

    optiondefaultdescription
    updateType"pushIn"How the URL gets updated by default (replace, replaceIn, push, pushIn).
    searchStringToObjectURLSearchParamsFunction to convert search string to object. (searchString: string) => Record<string, string | (string | null)[] | null | undefined>
    objectToSearchStringURLSearchParamsFunction to convert object to search string. (query: Record<string, string | (string | null)[] | null | undefined>) => string
    paramsundefinedDefine parameters at the provider level to be automatically available to hook calls.
    includeKnownParamsundefinedWhen true, include all parameters configured via the params option.
    includeAllParamsfalseInclude all parameters found in the URL even if not configured.
    removeDefaultsFromUrlfalseRemoves parameters from URL if their value matches their default (via withDefault).
    enableBatchingfalseTurns on batching (multiple consecutive setQueryParams calls result in one URL update).
  11. How to update the URL using UrlUpdateType

    master

    When using the setter function provided by use-query-params, you can specify how the URL should be updated using the UrlUpdateType. This determines whether the change adds to existing parameters or replaces them, and whether it affects the browser history.

    • replaceIn: Replaces just a single parameter, leaving the rest of the existing parameters as is.
    • replace: Replaces all parameters in the URL with only the ones specified in your update.
    • pushIn: Pushes a single parameter into the URL, leaving the rest as is. This adds a new entry to the browser history (the back button works).
    • push: Pushes only the specified parameters to the URL, replacing everything else. This also adds a new entry to the browser history.
  12. Wrap your application with QueryParamProvider

    master

    To use the useQueryParams hooks, you must wrap your application (or a part of it) in a QueryParamProvider. This provider connects the library to your routing system via an adapter and allows you to configure global options.

    For the root provider, you must provide an adapter. For nested providers, the adapter is optional as it will inherit the one from the parent provider, but you can provide new options to override or merge with parent settings.