Skip to content

kjj9677/react-url-params-state

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

11 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

react-url-params-state

A powerful React hook for synchronizing component state with URL query parameters. Keep your application state in sync with the URL automatically, supporting type safety, validation, and seamless navigation.

Features

  • ✨ Type-Safe: Full TypeScript support with automatic type inference
  • πŸ”„ Bidirectional Sync: URL ↔ State synchronization
  • 🎯 Multiple Types: Support for string, number, boolean, date, arrays, and objects
  • πŸ›‘οΈ Validation: Built-in validation with custom validators
  • πŸ”§ Customizable: Custom serializers and history modes
  • ⚑ Performance: Optimized with shallow comparison and memoization
  • 🌐 Universal: Works with Next.js, React Router, and any navigation library

Installation

npm install react-url-params-state
# or
yarn add react-url-params-state
# or
pnpm add react-url-params-state

Quick Start

import { useQueryParams } from 'react-url-params-state'

function SearchPage() {
  const [params, setParams] = useQueryParams({
    search: 'string',
    page: 'number',
    category: 'string'
  })

  return (
    <div>
      <input
        value={params.search || ''}
        onChange={(e) => setParams({ search: e.target.value })}
        placeholder="Search..."
      />

      <select
        value={params.category || ''}
        onChange={(e) => setParams({ category: e.target.value })}
      >
        <option value="">All Categories</option>
        <option value="electronics">Electronics</option>
        <option value="books">Books</option>
      </select>

      <button onClick={() => setParams({ page: (params.page || 0) + 1 })}>
        Next Page
      </button>
    </div>
  )
}

Supported Types

Basic Types

const [params, setParams] = useQueryParams({
  name: 'string',        // ?name=john
  age: 'number',         // ?age=25
  active: 'boolean',     // ?active=true
  birthday: 'date',      // ?birthday=2023-01-01T00:00:00.000Z
})

Arrays and Objects

const [params, setParams] = useQueryParams({
  tags: 'string[]',      // ?tags=react&tags=typescript
  filters: 'object',     // ?filters=%7B%22status%22%3A%22active%22%7D
})

Configuration Options

Default Values

const [params, setParams] = useQueryParams(
  {
    page: 'number',
    sort: 'string'
  },
  {
    defaultValues: {
      page: 1,
      sort: 'name'
    }
  }
)

Default Values Behavior:

  • Default values are automatically synced to the URL on initial mount
  • If a parameter is not present in the URL, its default value will be added
  • This ensures complete URL-state synchronization and better bookmarking support

Validation

const [params, setParams] = useQueryParams(
  {
    page: 'number',
    email: 'string'
  },
  {
    validation: {
      page: (value) => value > 0,
      email: (value) => value.includes('@')
    },
    validationFailureMode: 'remove', // 'keep' | 'remove' | 'useDefault'
    onError: (error, key, value) => {
      console.warn(`Validation failed for ${key}:`, error.message)
    }
  }
)

Validation Failure Modes:

  • 'keep' - Keep invalid values in URL
  • 'remove' - Remove invalid values from URL (default)
  • 'useDefault' - Replace invalid values with default values in URL

Custom Serializers

const [params, setParams] = useQueryParams(
  {
    coordinates: 'string'
  },
  {
    customSerializers: {
      coordinates: {
        serialize: (value: {lat: number, lng: number}) => `${value.lat},${value.lng}`,
        parse: (value: string) => {
          const [lat, lng] = value.split(',').map(Number)
          return { lat, lng }
        }
      }
    }
  }
)

History Mode

const [params, setParams] = useQueryParams(
  { search: 'string' },
  { defaultHistory: 'push' } // or 'replace'
)

// Or per update
setParams({ search: 'new search' }, 'push')

Advanced Usage

Sorting Query Parameters

const [params, setParams] = useQueryParams(
  { b: 'string', a: 'string' },
  { sortKeys: true } // URL will be ?a=value&b=value
)

Error Handling

const [params, setParams] = useQueryParams(
  { count: 'number' },
  {
    onError: (error, key, value) => {
      // Handle parsing or validation errors
      console.error(`Error with ${key}:`, error.message)
      // Could show user notification, fallback value, etc.
    }
  }
)

TypeScript Support

The library provides full type safety:

const [params, setParams] = useQueryParams({
  page: 'number',
  active: 'boolean',
  tags: 'string[]'
})

// βœ… TypeScript knows the exact types
params.page    // number | undefined
params.active  // boolean | undefined
params.tags    // string[] | undefined

// βœ… Type-safe updates
setParams({ page: 2 })              // βœ… OK
setParams({ page: 'invalid' })      // ❌ TypeScript error
setParams({ nonExistent: 'value' }) // ❌ TypeScript error

Browser Compatibility

  • βœ… Modern browsers (Chrome, Firefox, Safari, Edge)
  • βœ… React 16.8+ (hooks support required)
  • βœ… Next.js (App Router and Pages Router)
  • βœ… React Router
  • βœ… Any client-side navigation library

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT Β© jujuclub

About

A powerful React hook for synchronizing component state with URL query parameters

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published