# All files / src/_hooks useSet.ts

100% Statements 42/42
100% Branches 12/12
100% Functions 16/16
100% Lines 33/33

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    1036x

    92x
    92x
    92x
    92x
    92x

    92x

    92x

    4x
    4x
    4x

    92x

    6x
    6x
    6x

    92x

    12x
    12x
    12x
    12x

    122x

    92x

    3x

    92x

    2x

    92x
    1x

    92x

    5x
    5x

    92x
    1x

    92x

     import React from 'react'

    export interface SetHookConfig<T> {
      /**
       * @since 10.19.0
       */
      initialValue?: Set<T>
      /**
       * @since 10.19.0
       */
      onChange?: (newCollection: Set<T>) => void
      /**
       * @since 10.19.0
       */
      onAdd?: (item: T) => void
      /**
       * @since 10.19.0
       */
      onRemove?: (item: T) => void
    }

    export function useSet<T>({
      initialValue = new Set(),
      onChange,
      onAdd,
      onRemove,
    }: SetHookConfig<T> = {}) {
      const [collection, setCollection] = React.useState<Set<T>>(initialValue)

      const removeFromSet = React.useCallback(
        (collection: Set<T>, item: T) => {
          collection.delete(item)
          onRemove && onRemove(item)
          return new Set(collection)
        },
        [onRemove]
      )

      const addToSet = React.useCallback(
        (collection: Set<T>, item: T) => {
          collection.add(item)
          onAdd && onAdd(item)
          return new Set(collection)
        },
        [onAdd]
      )

      const updateCollection = React.useCallback(
        (updater: (prevCollection: Set<T>) => Set<T>) => {
          setCollection((prevCollection) => {
            const newCollection = updater(prevCollection)
            onChange && onChange(newCollection)
            return newCollection
          })
        },
        [onChange]
      )

      const has = React.useCallback((item: T) => collection.has(item), [collection])

      const add = React.useCallback(
        (item: T) =>
          updateCollection((prevCollection) => addToSet(prevCollection, item)),
        [addToSet, updateCollection]
      )

      const remove = React.useCallback(
        (item: T) =>
          updateCollection((prevCollection) => removeFromSet(prevCollection, item)),
        [removeFromSet, updateCollection]
      )

      const set = React.useCallback(
        (newCollection: Set<T>) => updateCollection(() => newCollection),
        [updateCollection]
      )

      const toggle = React.useCallback(
        (item: T) =>
          updateCollection((prevCollection) =>
            prevCollection.has(item)
              ? removeFromSet(prevCollection, item)
              : addToSet(prevCollection, item)
          ),
        [addToSet, removeFromSet, updateCollection]
      )

      const removeAll = React.useCallback(
        () => updateCollection(() => new Set()),
        [updateCollection]
      )

      return {
        collection,
        setCollection: set,
        has,
        add,
        remove,
        removeAll,
        toggle,
      }
    }