refactor: something
This commit is contained in:
58
src/components/setting/guard-state.tsx
Normal file
58
src/components/setting/guard-state.tsx
Normal file
@@ -0,0 +1,58 @@
|
||||
import { cloneElement, isValidElement, ReactNode, useRef } from "react";
|
||||
import noop from "../../utils/noop";
|
||||
|
||||
interface Props<Value> {
|
||||
value?: Value;
|
||||
valueProps?: string;
|
||||
onChangeProps?: string;
|
||||
onChange?: (value: Value) => void;
|
||||
onFormat?: (...args: any[]) => Value;
|
||||
onGuard?: (value: Value) => Promise<void>;
|
||||
onCatch?: (error: Error) => void;
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
function GuardState<T>(props: Props<T>) {
|
||||
const {
|
||||
value,
|
||||
children,
|
||||
valueProps = "value",
|
||||
onChangeProps = "onChange",
|
||||
onGuard = noop,
|
||||
onCatch = noop,
|
||||
onChange = noop,
|
||||
onFormat = (v: T) => v,
|
||||
} = props;
|
||||
|
||||
const lockRef = useRef(false);
|
||||
|
||||
if (isValidElement(children)) {
|
||||
const childProps = { ...children.props };
|
||||
|
||||
childProps[valueProps] = value;
|
||||
childProps[onChangeProps] = async (...args: any[]) => {
|
||||
// 多次操作无效
|
||||
if (lockRef.current) return;
|
||||
|
||||
lockRef.current = true;
|
||||
const oldValue = value;
|
||||
|
||||
try {
|
||||
const newValue = (onFormat as any)(...args);
|
||||
// 先在ui上响应操作
|
||||
onChange(newValue);
|
||||
await onGuard(newValue);
|
||||
} catch (err: any) {
|
||||
// 状态回退
|
||||
onChange(oldValue!);
|
||||
onCatch(err);
|
||||
}
|
||||
lockRef.current = false;
|
||||
};
|
||||
return cloneElement(children, childProps);
|
||||
}
|
||||
|
||||
return children as any;
|
||||
}
|
||||
|
||||
export default GuardState;
|
||||
Reference in New Issue
Block a user