feat: guard state supports debounce guard

This commit is contained in:
GyDi 2022-02-25 01:21:13 +08:00
parent f6e821ba6b
commit 8606af3616
No known key found for this signature in database
GPG Key ID: 1C95E0D3467B3084

View File

@ -5,6 +5,7 @@ interface Props<Value> {
value?: Value;
valueProps?: string;
onChangeProps?: string;
waitTime?: number;
onChange?: (value: Value) => void;
onFormat?: (...args: any[]) => Value;
onGuard?: (value: Value, oldValue: Value) => Promise<void>;
@ -18,6 +19,7 @@ function GuardState<T>(props: Props<T>) {
children,
valueProps = "value",
onChangeProps = "onChange",
waitTime = 0, // debounce wait time default 0
onGuard = noop,
onCatch = noop,
onChange = noop,
@ -25,8 +27,14 @@ function GuardState<T>(props: Props<T>) {
} = props;
const lockRef = useRef(false);
const saveRef = useRef(value);
const lastRef = useRef(0);
const timeRef = useRef<any>();
if (!isValidElement(children)) {
return children as any;
}
if (isValidElement(children)) {
const childProps = { ...children.props };
childProps[valueProps] = value;
@ -35,24 +43,45 @@ function GuardState<T>(props: Props<T>) {
if (lockRef.current) return;
lockRef.current = true;
const oldValue = value;
try {
const newValue = (onFormat as any)(...args);
// 先在ui上响应操作
onChange(newValue);
await onGuard(newValue, oldValue!);
const now = Date.now();
// save the old value
if (waitTime <= 0 || now - lastRef.current >= waitTime) {
saveRef.current = value;
}
lastRef.current = now;
if (waitTime <= 0) {
await onGuard(newValue, value!);
} else {
// debounce guard
clearTimeout(timeRef.current);
timeRef.current = setTimeout(async () => {
try {
await onGuard(newValue, saveRef.current!);
} catch (err: any) {
// 状态回退
onChange(oldValue!);
onChange(saveRef.current!);
onCatch(err);
}
}, waitTime);
}
} catch (err: any) {
// 状态回退
onChange(saveRef.current!);
onCatch(err);
}
lockRef.current = false;
};
return cloneElement(children, childProps);
}
return children as any;
}
export default GuardState;