Removed useless hooks
This commit is contained in:
@@ -1,81 +0,0 @@
|
|||||||
import { useRef } from "react";
|
|
||||||
import { usePersistFn } from "./usePersistFn";
|
|
||||||
|
|
||||||
export interface UseCompositionReturn<
|
|
||||||
T extends HTMLInputElement | HTMLTextAreaElement,
|
|
||||||
> {
|
|
||||||
onCompositionStart: React.CompositionEventHandler<T>;
|
|
||||||
onCompositionEnd: React.CompositionEventHandler<T>;
|
|
||||||
onKeyDown: React.KeyboardEventHandler<T>;
|
|
||||||
isComposing: () => boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UseCompositionOptions<
|
|
||||||
T extends HTMLInputElement | HTMLTextAreaElement,
|
|
||||||
> {
|
|
||||||
onKeyDown?: React.KeyboardEventHandler<T>;
|
|
||||||
onCompositionStart?: React.CompositionEventHandler<T>;
|
|
||||||
onCompositionEnd?: React.CompositionEventHandler<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
type TimerResponse = ReturnType<typeof setTimeout>;
|
|
||||||
|
|
||||||
export function useComposition<
|
|
||||||
T extends HTMLInputElement | HTMLTextAreaElement = HTMLInputElement,
|
|
||||||
>(options: UseCompositionOptions<T> = {}): UseCompositionReturn<T> {
|
|
||||||
const {
|
|
||||||
onKeyDown: originalOnKeyDown,
|
|
||||||
onCompositionStart: originalOnCompositionStart,
|
|
||||||
onCompositionEnd: originalOnCompositionEnd,
|
|
||||||
} = options;
|
|
||||||
|
|
||||||
const c = useRef(false);
|
|
||||||
const timer = useRef<TimerResponse | null>(null);
|
|
||||||
const timer2 = useRef<TimerResponse | null>(null);
|
|
||||||
|
|
||||||
const onCompositionStart = usePersistFn((e: React.CompositionEvent<T>) => {
|
|
||||||
if (timer.current) {
|
|
||||||
clearTimeout(timer.current);
|
|
||||||
timer.current = null;
|
|
||||||
}
|
|
||||||
if (timer2.current) {
|
|
||||||
clearTimeout(timer2.current);
|
|
||||||
timer2.current = null;
|
|
||||||
}
|
|
||||||
c.current = true;
|
|
||||||
originalOnCompositionStart?.(e);
|
|
||||||
});
|
|
||||||
|
|
||||||
const onCompositionEnd = usePersistFn((e: React.CompositionEvent<T>) => {
|
|
||||||
// 使用两层 setTimeout 来处理 Safari 浏览器中 compositionEnd 先于 onKeyDown 触发的问题
|
|
||||||
timer.current = setTimeout(() => {
|
|
||||||
timer2.current = setTimeout(() => {
|
|
||||||
c.current = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
originalOnCompositionEnd?.(e);
|
|
||||||
});
|
|
||||||
|
|
||||||
const onKeyDown = usePersistFn((e: React.KeyboardEvent<T>) => {
|
|
||||||
// 在 composition 状态下,阻止 ESC 和 Enter(非 shift+Enter)事件的冒泡
|
|
||||||
if (
|
|
||||||
c.current &&
|
|
||||||
(e.key === "Escape" || (e.key === "Enter" && !e.shiftKey))
|
|
||||||
) {
|
|
||||||
e.stopPropagation();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
originalOnKeyDown?.(e);
|
|
||||||
});
|
|
||||||
|
|
||||||
const isComposing = usePersistFn(() => {
|
|
||||||
return c.current;
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
onCompositionStart,
|
|
||||||
onCompositionEnd,
|
|
||||||
onKeyDown,
|
|
||||||
isComposing,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
import { useRef } from "react";
|
|
||||||
|
|
||||||
type noop = (...args: any[]) => any;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* usePersistFn instead of useCallback to reduce cognitive load
|
|
||||||
*/
|
|
||||||
export function usePersistFn<T extends noop>(fn: T) {
|
|
||||||
const fnRef = useRef<T>(fn);
|
|
||||||
fnRef.current = fn;
|
|
||||||
|
|
||||||
const persistFn = useRef<T>(null);
|
|
||||||
if (!persistFn.current) {
|
|
||||||
persistFn.current = function (this: unknown, ...args) {
|
|
||||||
return fnRef.current!.apply(this, args);
|
|
||||||
} as T;
|
|
||||||
}
|
|
||||||
|
|
||||||
return persistFn.current!;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user