# 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
    522x
    522x
    522x
    522x
    522x
    522x
    522x
    26x
    26x
    496x
    522x
    10x
    10x
    10x
    10x
    486x
    518x
    5x
    5x
    5x
    5x
    481x
    481x
    481x
     /* 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>,
    > {
      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];
    }