# All files / src useEnsuredState.ts

100% Statements 50/50
100% Branches 11/11
100% Functions 1/1
100% Lines 50/50

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
    511x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    1x
    521x
    521x
    521x
    521x
    521x
    521x
    521x
    26x
    26x
    495x
    521x
    10x
    10x
    10x
    10x
    485x
    517x
    5x
    5x
    5x
    5x
    480x
    480x
    480x
     /* eslint-disable react-hooks/rules-of-hooks */
    import type { Dispatch } from "react";
    import { useState } from "react";
    import type { UseStateInitializer, UseStateSetter } from "./types.js";

    /**
     * @internal
     * @remarks \@since 6.0.0
     */
    export interface EnsuredStateOptions<
      V,
      Setter extends Dispatch<V> | UseStateSetter<V> = UseStateSetter<V>,
    > {
      value?: V;
      setValue?: Setter;
      defaultValue?: UseStateInitializer<V>;
    }

    /**
     * This is used to dynamically allow controlling hooks by providing a `value` +
     * `setValue` or defaulting to uncontrolled behavior with local state.
     *
     * @internal
     * @remarks \@since 6.0.0
     */
    export function useEnsuredState<
      V,
      Setter extends Dispatch<V> | UseStateSetter<V>,
    >(
      options: EnsuredStateOptions<V, Setter>
    ): readonly [value: V, setValue: Setter] {
      const { value, setValue, defaultValue } = options;
      if (typeof value !== "undefined" && typeof setValue !== "undefined") {
        return [value, setValue];
      }

      if (typeof value !== "undefined" || typeof setValue !== "undefined") {
        throw new Error(
          "Both a `value` and `setValue` must be defined for controlled components."
        );
      }

      if (typeof defaultValue === "undefined") {
        throw new Error(
          "A `defaultValue` must be defined for uncontrolled components."
        );
      }

      return useState(defaultValue) as [value: V, setValue: Setter];
    }