-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.tsx
39 lines (33 loc) · 1.17 KB
/
index.tsx
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
import { useState, useCallback } from 'react';
// Either use the callback `setState` signature or just a "void"
type OnChange<T> = (v: React.SetStateAction<T>) => T | void;
type StateUpdater<T> = (v: T) => T;
export function useControlledState<
TState,
TOnChange extends Function = OnChange<TState>
>(value: TState, onChange?: TOnChange): [TState, OnChange<TState>] {
if (typeof value == 'function') {
throw new TypeError(
'Functions are not supported as state values in the `useControlledState` hook.'
);
}
const [uncontrolledValue, setUncontrolledValue] = useState(value);
const onControlledChange = useCallback(
(setStateArgument: React.SetStateAction<TState>) => {
if (onChange) {
let changeValue: TState | StateUpdater<TState> = setStateArgument;
if (typeof changeValue === 'function') {
changeValue = (setStateArgument as StateUpdater<TState>)(value);
}
onChange(changeValue);
}
},
[onChange, value]
);
if (typeof onChange === 'function') {
// Controlled version
return [value, onControlledChange];
}
// Uncontrolled version
return [uncontrolledValue, setUncontrolledValue];
}