diff --git a/src/InputNumber.tsx b/src/InputNumber.tsx index b5def745..7cab51d1 100644 --- a/src/InputNumber.tsx +++ b/src/InputNumber.tsx @@ -7,6 +7,7 @@ import StepHandler from './StepHandler'; import { getNumberPrecision, num2str, validateNumber } from './utils/numberUtil'; import useCursor from './hooks/useCursor'; import useUpdateEffect from './hooks/useUpdateEffect'; +import useFrame from './hooks/useFrame'; /** * We support `stringMode` which need handle correct type when user call in onChange @@ -323,6 +324,8 @@ const InputNumber = React.forwardRef( }; // ========================== User Input ========================== + const onNextPromise = useFrame(); + // >>> Collect input value const collectInputValue = (inputStr: string) => { recordCursor(); @@ -338,6 +341,22 @@ const InputNumber = React.forwardRef( triggerValueUpdate(finalDecimal, true); } } + + // Trigger onInput later to let user customize value if they want do handle something after onChange + onInput?.(inputStr); + + // optimize for chinese input experience + // https://github.com/ant-design/ant-design/issues/8196 + onNextPromise(() => { + let nextInputStr = inputStr; + if (!parser) { + nextInputStr = inputStr.replace(/。/g, '.'); + } + + if (nextInputStr !== inputStr) { + collectInputValue(nextInputStr); + } + }); }; // >>> Composition @@ -353,18 +372,7 @@ const InputNumber = React.forwardRef( // >>> Input const onInternalInput: React.ChangeEventHandler = (e) => { - let inputStr = e.target.value; - - // optimize for chinese input experience - // https://github.com/ant-design/ant-design/issues/8196 - if (!parser) { - inputStr = inputStr.replace(/。/g, '.'); - } - - collectInputValue(inputStr); - - // Trigger onInput later to let user customize value if they want do handle something after onChange - onInput?.(inputStr); + collectInputValue(e.target.value); }; // ============================= Step ============================= diff --git a/src/hooks/useFrame.ts b/src/hooks/useFrame.ts new file mode 100644 index 00000000..d0902577 --- /dev/null +++ b/src/hooks/useFrame.ts @@ -0,0 +1,23 @@ +import { useRef, useEffect } from 'react'; +import raf from 'rc-util/lib/raf'; + +/** + * Always trigger latest once when call multiple time + */ +export default () => { + const idRef = useRef(0); + + const cleanUp = () => { + raf.cancel(idRef.current); + }; + + useEffect(() => cleanUp, []); + + return (callback: () => void) => { + cleanUp(); + + idRef.current = raf(() => { + callback(); + }); + }; +}; diff --git a/tests/github.test.tsx b/tests/github.test.tsx index cd269cad..19c4c38f 100644 --- a/tests/github.test.tsx +++ b/tests/github.test.tsx @@ -11,6 +11,7 @@ describe('InputNumber.Github', () => { }); afterEach(() => { + jest.clearAllTimers(); jest.useRealTimers(); }); @@ -340,6 +341,14 @@ describe('InputNumber.Github', () => { const onChange = jest.fn(); const wrapper = mount(); wrapper.changeValue('8。1'); + + act(() => { + jest.runAllTimers(); + wrapper.update(); + }); + + wrapper.update(); + expect(wrapper.getInputValue()).toEqual('8.1'); expect(onChange).toHaveBeenCalledWith(8.1); });