• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

liferay / clay / 18367279023

08 Oct 2025 10:57AM UTC coverage: 69.501%. Remained the same
18367279023

push

github

web-flow
Merge pull request #6181 from gabsprates/LPD-63674

LPD-63674 Union types to declare InternalDispatch<Value> as a generic function leads to `any` type

2992 of 4926 branches covered (60.74%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

12 existing lines in 1 file now uncovered.

5647 of 7504 relevant lines covered (75.25%)

56.83 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

9.68
/packages/clay-shared/src/useControlledState.ts
1
/**
2
 * SPDX-FileCopyrightText: © 2021 Liferay, Inc. <https://liferay.com>
3
 * SPDX-License-Identifier: BSD-3-Clause
4
 */
5

6
import {useCallback, useRef, useState} from 'react';
3✔
7
import warning from 'warning';
3✔
8

9
export type InternalDispatch<Value> = (value: Value) => void;
10

11
type Props<Value> = {
12
        defaultName: string;
13
        handleName: string;
14
        name: string;
15
        defaultValue?: Value | (() => Value);
16
        onChange?: InternalDispatch<Value>;
17
        value?: Value;
18
};
19

20
export function useControlledState<Value>({
3✔
21
        defaultName,
22
        defaultValue,
23
        handleName,
24
        name,
25
        onChange,
26
        value,
27
}: Props<Value>) {
28
        const [stateValue, setStateValue] = useState(
×
29
                defaultValue === undefined ? value : defaultValue
×
30
        );
31

32
        const ref = useRef(value !== undefined);
×
UNCOV
33
        const wasControlled = ref.current;
×
UNCOV
34
        const isControlled = value !== undefined;
×
35

UNCOV
36
        if (wasControlled !== isControlled) {
×
UNCOV
37
                console.warn(
×
38
                        `WARN: A component changed from ${
39
                                wasControlled ? 'controlled' : 'uncontrolled'
×
40
                        } to ${
41
                                isControlled ? 'controlled' : 'uncontrolled'
×
42
                        }. This is likely caused by the value changing from a defined to undefined, which should not happen. Decide between using a controlled or uncontrolled '${name}' prop for the lifetime of the component.`
43
                );
44
        }
45

UNCOV
46
        ref.current = isControlled;
×
47

48
        warning(
×
49
                !(typeof onChange === 'undefined' && typeof value !== 'undefined'),
×
50
                `You provided a '${name}' prop for a component without a handler '${handleName}'. This will render the component with an internal state, if the component is to be uncontrolled, use '${defaultName}'. Otherwise, set the '${handleName}' handler.`
51
        );
52

UNCOV
53
        const setValue = useCallback(
×
54
                (value: Value) => {
55
                        if (!isControlled) {
×
UNCOV
56
                                setStateValue(value);
×
57
                        }
58

UNCOV
59
                        if (onChange) {
×
UNCOV
60
                                onChange(value);
×
61
                        }
62
                },
63
                [isControlled, onChange]
64
        );
65

UNCOV
66
        if (!isControlled) {
×
UNCOV
67
                value = stateValue;
×
68
        }
69

UNCOV
70
        return [value, setValue, !isControlled] as [
×
71
                Value,
72
                InternalDispatch<Value>,
73
                boolean
74
        ];
75
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc