my-swiss-knife: - v1.9.9
    Preparing search index...

    Function useSelection

    • A custom React hook that provides selection logic for a list of items.

      This hook allows you to manage selected items using their unique key. It provides utilities for selecting, deselecting, toggling selection, and checking selection state.

      Type Parameters

      • D extends ObjectType

        The type of data objects in the list.

      • K extends string | number | symbol = StringNumberKeys<D>

        The key in each object that uniquely identifies it (must be of type string or number).

      Parameters

      • data: D[]

        The array of items to manage selection for.

      • key: K

        The object property to use as the unique identifier.

      Returns {
          deselectAll: () => void;
          deselectItem: (item: D) => void;
          isSelected: { everything: boolean; something: boolean };
          selectedData: Record<string | number, D>;
          selectItem: (item: D) => void;
          toggleSelectAll: () => void;
      }

      Object containing selection control functions and state:

      • toggleSelectAll: Toggles selection state of all items.
      • isSelected.something: true if at least one item is selected.
      • isSelected.everything: true if all items in the list are selected.
      • selectedData: A map of currently selected items, keyed by their unique identifier.
      • selectItem: Selects a specific item.
      • deselectItem: Deselects a specific item.
      • deselectAll: Clears all selected items.
      const {
      toggleSelectAll,
      isSelected,
      selectedData,
      selectItem,
      deselectItem,
      deselectAll
      } = useSelection(users, 'user_id');

      <button onClick={toggleSelectAll}>
      {isSelected.everything ? 'Unselect All' : 'Select All'}
      </button>

      {users.map(user => (
      <div key={user.user_id}>
      <input
      type="checkbox"
      checked={!!selectedData[user.user_id]}
      onChange={() =>
      selectedData[user.user_id]
      ? deselectItem(user)
      : selectItem(user)
      }
      />
      {user.name}
      </div>
      ))}
      export const useSelection = <
      D extends ObjectType,
      K extends keyof D = StringNumberKeys<D>,
      >(data: D[], key: K): {
      toggleSelectAll: () => void;
      isSelected: {
      something: boolean;
      everything: boolean;
      };
      selectedData: Record<string | number, D>;
      selectItem: (item: D) => void;
      deselectItem: (item: D) => void;
      deselectAll: () => void;
      } => {

      const emptyState = {} as HashMapType<D, K>
      const [selectedData, setSelectedData] = useState(emptyState)

      const isSelected = useMemo(() => {
      const selectedKeys = Object.keys(selectedData)
      return {
      something: selectedKeys.length > 0,
      everything: data.length > 0 && selectedKeys.length >= data.length && data.every(item => {
      return asKey(item[key]) in selectedData
      })
      }
      }, [selectedData, data])

      const toggleSelectAll = useCallback(() => {
      if (isSelected.everything) {
      setSelectedData(prevState => {
      const newState = { ...prevState }
      data.forEach(item => {
      delete newState[asKey<D[K]>(item[key])];
      })
      return newState
      })
      } else {
      setSelectedData(prevState => {
      const newState = { ...prevState }
      data.forEach(item => {
      newState[asKey<D[K]>(item[key])] = item
      })
      return newState
      })
      }
      }, [data, selectedData])

      const selectItem = useCallback((item: D) => {
      setSelectedData(prevState => {
      const id = asKey(item[key])
      return {
      ...prevState,
      [id]: item
      }
      })
      }, [])

      const deselectItem = useCallback((item: D) => {
      setSelectedData(prevState => {
      const newState = { ...prevState }
      delete newState[asKey<D[K]>(item[key])]
      return newState
      })
      }, [])

      const deselectAll = useCallback(() => {
      setSelectedData(emptyState)
      }, [])

      return {
      toggleSelectAll,
      isSelected,
      selectedData,
      selectItem,
      deselectItem,
      deselectAll
      }
      }