-
-
Notifications
You must be signed in to change notification settings - Fork 3.2k
/
Copy pathuseMediatedState.ts
38 lines (31 loc) · 1.04 KB
/
useMediatedState.ts
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
import { Dispatch, SetStateAction, useCallback, useRef, useState } from 'react';
export interface StateMediator<S = any> {
(newState: any): S;
(newState: any, dispatch: Dispatch<SetStateAction<S>>): void;
}
export type UseMediatedStateReturn<S = any> = [S, Dispatch<SetStateAction<S>>];
export function useMediatedState<S = undefined>(
mediator: StateMediator<S | undefined>
): UseMediatedStateReturn<S | undefined>;
export function useMediatedState<S = any>(
mediator: StateMediator<S>,
initialState: S
): UseMediatedStateReturn<S>;
export function useMediatedState<S = any>(
mediator: StateMediator<S>,
initialState?: S
): UseMediatedStateReturn<S> {
const mediatorFn = useRef(mediator);
const [state, setMediatedState] = useState<S>(initialState!);
const setState = useCallback(
(newState: any) => {
if (mediatorFn.current.length === 2) {
mediatorFn.current(newState, setMediatedState);
} else {
setMediatedState(mediatorFn.current(newState));
}
},
[state]
);
return [state, setState];
}