Skip to content

⬅️ Back to Table of Contents

📄 useUrlSearchParams

📊 Analysis Summary

Metric Count
🔧 Functions 7
📦 Imports 6
🟢 Vue Composition API 2
📐 Interfaces 1
📑 Type Aliases 1

📚 Table of Contents

🛠️ File Location:

📂 packages/core/useUrlSearchParams/index.ts

📦 Imports

Name Source
ConfigurableWindow ../_configurable
watchPausable @vueuse/shared
nextTick vue
reactive vue
defaultWindow ../_configurable
useEventListener ../useEventListener

Vue Composition API

Name Type Reactive Variables Composables
reactive reactive none none
reactive reactive none none

Functions

useUrlSearchParams(mode: 'history' | 'hash' | 'hash-params', options: UseUrlSearchParamsOptions<T>): T

Reactive URLSearchParams

Parameters:

  • mode any: No description
  • options any: No description

See: https://vueuse.org/useUrlSearchParams

Raw JSDoc
/**
 * Reactive URLSearchParams
 *
 * @see https://vueuse.org/useUrlSearchParams
 * @param mode
 * @param options
 */

Calls:

  • params.toString
  • reactive (from vue)
  • hash.indexOf
  • hash.slice
  • (window.location.hash || '').replace
  • stringify
  • getRawParams
  • Object.keys
  • params.keys
  • params.getAll
  • params.get
  • unusedKeys.delete
  • Array.from(unusedKeys).forEach
  • watchPausable (from @vueuse/shared)
  • Object.keys(state).forEach
  • Array.isArray
  • mapEntry.forEach
  • params.append
  • params.delete
  • params.set
  • write
  • pause
  • updateState
  • window.history.replaceState
  • constructQuery
  • window.history.pushState
  • nextTick (from vue)
  • resume
  • read
  • useEventListener (from ../useEventListener)
  • initial.keys().next
  • Object.assign
Code
export function useUrlSearchParams<T extends Record<string, any> = UrlParams>(
  mode: 'history' | 'hash' | 'hash-params' = 'history',
  options: UseUrlSearchParamsOptions<T> = {},
): T {
  const {
    initialValue = {},
    removeNullishValues = true,
    removeFalsyValues = false,
    write: enableWrite = true,
    writeMode = 'replace',
    window = defaultWindow!,
    stringify = params => params.toString(),
  } = options

  if (!window)
    return reactive(initialValue) as T

  const state: Record<string, any> = reactive({})

  function getRawParams() {
    if (mode === 'history') {
      return window.location.search || ''
    }
    else if (mode === 'hash') {
      const hash = window.location.hash || ''
      const index = hash.indexOf('?')
      return index > 0 ? hash.slice(index) : ''
    }
    else {
      return (window.location.hash || '').replace(/^#/, '')
    }
  }

  function constructQuery(params: URLSearchParams) {
    const stringified = stringify(params)
    if (mode === 'history')
      return `${stringified ? `?${stringified}` : ''}${window.location.hash || ''}`
    if (mode === 'hash-params')
      return `${window.location.search || ''}${stringified ? `#${stringified}` : ''}`
    const hash = window.location.hash || '#'
    const index = hash.indexOf('?')
    if (index > 0)
      return `${window.location.search || ''}${hash.slice(0, index)}${stringified ? `?${stringified}` : ''}`
    return `${window.location.search || ''}${hash}${stringified ? `?${stringified}` : ''}`
  }

  function read() {
    return new URLSearchParams(getRawParams())
  }

  function updateState(params: URLSearchParams) {
    const unusedKeys = new Set(Object.keys(state))
    for (const key of params.keys()) {
      const paramsForKey = params.getAll(key)
      state[key] = paramsForKey.length > 1
        ? paramsForKey
        : (params.get(key) || '')
      unusedKeys.delete(key)
    }
    Array.from(unusedKeys).forEach(key => delete state[key])
  }

  const { pause, resume } = watchPausable(
    state,
    () => {
      const params = new URLSearchParams('')
      Object.keys(state).forEach((key) => {
        const mapEntry = state[key]
        if (Array.isArray(mapEntry))
          mapEntry.forEach(value => params.append(key, value))
        else if (removeNullishValues && mapEntry == null)
          params.delete(key)
        else if (removeFalsyValues && !mapEntry)
          params.delete(key)
        else
          params.set(key, mapEntry)
      })
      write(params, false)
    },
    { deep: true },
  )

  function write(params: URLSearchParams, shouldUpdate: boolean, shouldWriteHistory = true) {
    pause()

    if (shouldUpdate)
      updateState(params)

    if (writeMode === 'replace') {
      window.history.replaceState(
        window.history.state,
        window.document.title,
        window.location.pathname + constructQuery(params),
      )
    }
    else {
      if (shouldWriteHistory) {
        window.history.pushState(
          window.history.state,
          window.document.title,
          window.location.pathname + constructQuery(params),
        )
      }
    }

    nextTick(() => resume())
  }

  function onChanged() {
    if (!enableWrite)
      return

    write(read(), true, false)
  }

  const listenerOptions = { passive: true }

  useEventListener(window, 'popstate', onChanged, listenerOptions)
  if (mode !== 'history')
    useEventListener(window, 'hashchange', onChanged, listenerOptions)

  const initial = read()
  if (initial.keys().next().value)
    updateState(initial)
  else
    Object.assign(state, initialValue)

  return state as T
}

Internal helpers

Declared inside another function in this file.

getRawParams(): string

Returns: string

Calls:

  • hash.indexOf
  • hash.slice
  • (window.location.hash || '').replace
Code
function getRawParams() {
    if (mode === 'history') {
      return window.location.search || ''
    }
    else if (mode === 'hash') {
      const hash = window.location.hash || ''
      const index = hash.indexOf('?')
      return index > 0 ? hash.slice(index) : ''
    }
    else {
      return (window.location.hash || '').replace(/^#/, '')
    }
  }

constructQuery(params: URLSearchParams): string

Parameters:

  • params URLSearchParams

Returns: string

Calls:

  • stringify
  • hash.indexOf
  • hash.slice
Code
function constructQuery(params: URLSearchParams) {
    const stringified = stringify(params)
    if (mode === 'history')
      return `${stringified ? `?${stringified}` : ''}${window.location.hash || ''}`
    if (mode === 'hash-params')
      return `${window.location.search || ''}${stringified ? `#${stringified}` : ''}`
    const hash = window.location.hash || '#'
    const index = hash.indexOf('?')
    if (index > 0)
      return `${window.location.search || ''}${hash.slice(0, index)}${stringified ? `?${stringified}` : ''}`
    return `${window.location.search || ''}${hash}${stringified ? `?${stringified}` : ''}`
  }

read(): URLSearchParams

Returns: URLSearchParams

Calls:

  • getRawParams
Code
function read() {
    return new URLSearchParams(getRawParams())
  }

updateState(params: URLSearchParams): void

Parameters:

  • params URLSearchParams

Returns: void

Calls:

  • Object.keys
  • params.keys
  • params.getAll
  • params.get
  • unusedKeys.delete
  • Array.from(unusedKeys).forEach
Code
function updateState(params: URLSearchParams) {
    const unusedKeys = new Set(Object.keys(state))
    for (const key of params.keys()) {
      const paramsForKey = params.getAll(key)
      state[key] = paramsForKey.length > 1
        ? paramsForKey
        : (params.get(key) || '')
      unusedKeys.delete(key)
    }
    Array.from(unusedKeys).forEach(key => delete state[key])
  }

write(params: URLSearchParams, shouldUpdate: boolean, shouldWriteHistory: boolean): void

Parameters:

  • params URLSearchParams
  • shouldUpdate boolean
  • shouldWriteHistory boolean

Returns: void

Calls:

  • pause
  • updateState
  • window.history.replaceState
  • constructQuery
  • window.history.pushState
  • nextTick (from vue)
  • resume
Code
function write(params: URLSearchParams, shouldUpdate: boolean, shouldWriteHistory = true) {
    pause()

    if (shouldUpdate)
      updateState(params)

    if (writeMode === 'replace') {
      window.history.replaceState(
        window.history.state,
        window.document.title,
        window.location.pathname + constructQuery(params),
      )
    }
    else {
      if (shouldWriteHistory) {
        window.history.pushState(
          window.history.state,
          window.document.title,
          window.location.pathname + constructQuery(params),
        )
      }
    }

    nextTick(() => resume())
  }

onChanged(): void

Returns: void

Calls:

  • write
  • read
Code
function onChanged() {
    if (!enableWrite)
      return

    write(read(), true, false)
  }

Interfaces

UseUrlSearchParamsOptions<T>

Interface Code
export interface UseUrlSearchParamsOptions<T> extends ConfigurableWindow {
  /**
   * @default true
   */
  removeNullishValues?: boolean

  /**
   * @default false
   */
  removeFalsyValues?: boolean

  /**
   * @default {}
   */
  initialValue?: T

  /**
   * Write back to `window.history` automatically
   *
   * @default true
   */
  write?: boolean

  /**
   * Write mode for `window.history` when `write` is enabled
   * - `replace`: replace the current history entry
   * - `push`: push a new history entry
   * @default 'replace'
   */
  writeMode?: 'replace' | 'push'

  /**
   * Custom function to serialize URL parameters
   * When provided, this function will be used instead of the default URLSearchParams.toString()
   * @param params The URLSearchParams object to serialize
   * @returns The serialized query string (should not include the leading '?' or '#')
   */
  stringify?: (params: URLSearchParams) => string
}

Properties

Name Type Optional Description
removeNullishValues boolean not shown
removeFalsyValues boolean not shown
initialValue T not shown
write boolean not shown
writeMode 'replace' \| 'push' not shown
stringify (params: URLSearchParams) => string not shown

Type Aliases

UrlParams

type UrlParams = Record<string, string[] | string>;

Generated by Syntax Scribe