From 4c20ed7126ba3f36c7d0755353b7399eb3666913 Mon Sep 17 00:00:00 2001
From: "Alex.huxiyang" <1872591453@qq.com>
Date: Fri, 2 Aug 2024 18:44:30 +0800
Subject: [PATCH] fix(inputNumber): correct onChange, onOverlimit event
triggering timing when async & sync (#2509)
* fix(inputNumber): onOverlimit and onchange
* fix(inputNumber): onOverlimit and onchange
* chore: unify demo
* chore: add test
* chore: add test
* fix: not overlimit
* fix: reset demo
* fix: test
---
.../__tests__/inputnumber.spec.tsx | 17 +++++++
src/packages/inputnumber/demos/h5/demo3.tsx | 12 ++++-
src/packages/inputnumber/demos/h5/demo8.tsx | 15 ++++++-
src/packages/inputnumber/demos/taro/demo3.tsx | 3 ++
src/packages/inputnumber/demos/taro/demo8.tsx | 13 +++++-
src/packages/inputnumber/inputnumber.taro.tsx | 45 ++++++++++++++-----
src/packages/inputnumber/inputnumber.tsx | 43 +++++++++++++-----
7 files changed, 123 insertions(+), 25 deletions(-)
diff --git a/src/packages/inputnumber/__tests__/inputnumber.spec.tsx b/src/packages/inputnumber/__tests__/inputnumber.spec.tsx
index eb770e5734..606fec2100 100644
--- a/src/packages/inputnumber/__tests__/inputnumber.spec.tsx
+++ b/src/packages/inputnumber/__tests__/inputnumber.spec.tsx
@@ -157,3 +157,20 @@ test('allowEmpty', () => {
expect(container.querySelector('input')?.value).toBe('')
})
})
+
+test('should overlimit when input', () => {
+ const change = vi.fn()
+ const overlimit = vi.fn()
+ const { container } = render(
+
+ )
+ const input = container.querySelectorAll('input')[0]
+ input.value = '200'
+ fireEvent.input(input)
+ expect(change).toBeCalled()
+})
diff --git a/src/packages/inputnumber/demos/h5/demo3.tsx b/src/packages/inputnumber/demos/h5/demo3.tsx
index 8fcf1e3a68..2790c69244 100644
--- a/src/packages/inputnumber/demos/h5/demo3.tsx
+++ b/src/packages/inputnumber/demos/h5/demo3.tsx
@@ -2,11 +2,19 @@ import React from 'react'
import { InputNumber, Toast } from '@nutui/nutui-react'
const Demo3 = () => {
- const overlimit = () => {
+ const overlimit = (e: any) => {
Toast.show({ content: '超出限制事件触发', icon: 'warn' })
}
return (
-
+ {
+ console.log('onChange', v)
+ }}
+ />
)
}
export default Demo3
diff --git a/src/packages/inputnumber/demos/h5/demo8.tsx b/src/packages/inputnumber/demos/h5/demo8.tsx
index fc9c270ad7..e66949dddf 100644
--- a/src/packages/inputnumber/demos/h5/demo8.tsx
+++ b/src/packages/inputnumber/demos/h5/demo8.tsx
@@ -3,13 +3,26 @@ import { InputNumber, Toast } from '@nutui/nutui-react'
const Demo8 = () => {
const [inputValue, setInputValue] = useState(0)
+ const overlimit = (e: any) => {
+ console.log('超出限制事件触发', e)
+ }
const onChange = (value: string | number) => {
Toast.show({ icon: 'loading', content: '异步演示2秒后更改' })
+ console.log('onChange', value)
setTimeout(() => {
setInputValue(Number(value))
Toast.clear()
}, 2000)
}
- return
+ return (
+
+ )
}
export default Demo8
diff --git a/src/packages/inputnumber/demos/taro/demo3.tsx b/src/packages/inputnumber/demos/taro/demo3.tsx
index 61b92cb9b0..e3864406eb 100644
--- a/src/packages/inputnumber/demos/taro/demo3.tsx
+++ b/src/packages/inputnumber/demos/taro/demo3.tsx
@@ -22,6 +22,9 @@ const Demo3 = () => {
min={10}
max={20}
onOverlimit={overlimit}
+ onChange={(v) => {
+ console.log('onChange', v)
+ }}
/>
{
SetToastType(type)
SetShow(true)
}
+ const overlimit = (e: any) => {
+ console.log('超出限制事件触发', e)
+ }
const onChange = (value: string | number) => {
toastShow('异步演示 2 秒后更改', 'loading')
+ console.log('onChange', value)
setTimeout(() => {
setInputValue(Number(value))
SetShow(false)
@@ -21,7 +25,14 @@ const Demo8 = () => {
}
return (
<>
-
+
string
onPlus: (e: React.MouseEvent) => void
onMinus: (e: React.MouseEvent) => void
- onOverlimit: (e: React.MouseEvent) => void
+ onOverlimit: (e: React.MouseEvent | ChangeEvent) => void
onBlur: (e: React.FocusEvent) => void
onFocus: (e: React.FocusEvent) => void
onChange: (
@@ -181,7 +181,25 @@ export const InputNumber: FunctionComponent<
if (text === '-') return null
return text
}
- const handleInputChange = (e: React.ChangeEvent) => {
+ const clampValue = (valueStr: string | null) => {
+ if (valueStr === null) return defaultValue
+ const val = Number(parseFloat(valueStr || '0').toFixed(digits))
+ return Math.max(Number(min), Math.min(Number(max), val))
+ }
+ const handleValueChange = (
+ valueStr: string | null,
+ e: React.ChangeEvent
+ ) => {
+ const val = clampValue(valueStr)
+ // input暂不触发onOverlimit
+ // if (val !== Number(e.target.value)) {
+ // onOverlimit?.(e)
+ // }
+ if (val !== Number(shadowValue)) {
+ onChange?.(val, e)
+ }
+ }
+ const handleInputChange = (e: ChangeEvent) => {
// 设置 input 值, 在 blur 时格式化
setInputValue(e.target.value)
const valueStr = parseValue(e.target.value)
@@ -192,11 +210,9 @@ export const InputNumber: FunctionComponent<
setShadowValue(defaultValue)
}
} else {
- setShadowValue(valueStr as any)
- }
- if (!async) {
- onChange?.(parseFloat(valueStr || '0').toFixed(digits) as any, e)
+ setShadowValue(clampValue(valueStr) as any)
}
+ !async && handleValueChange(valueStr, e)
}
const handleFocus = (e: React.FocusEvent) => {
setFocused(true)
@@ -205,15 +221,22 @@ export const InputNumber: FunctionComponent<
? bound(Number(shadowValue), Number(min), Number(max)).toString()
: ''
)
- onFocus && onFocus(e)
+ onFocus?.(e)
}
const handleBlur = (e: React.FocusEvent) => {
setFocused(false)
- onBlur && onBlur(e)
- if (async) {
- const valueStr = parseValue(e.target.value)
- onChange?.(parseFloat(valueStr || '0').toFixed(digits) as any, e)
+ onBlur?.(e)
+ const valueStr = parseValue(e.target.value)
+ if (valueStr === null) {
+ if (allowEmpty) {
+ setShadowValue(null)
+ } else {
+ setShadowValue(defaultValue)
+ }
+ } else {
+ setShadowValue(clampValue(valueStr) as any)
}
+ async && handleValueChange(valueStr, e)
}
return (
diff --git a/src/packages/inputnumber/inputnumber.tsx b/src/packages/inputnumber/inputnumber.tsx
index 45cfe6ae01..9c1dcee620 100644
--- a/src/packages/inputnumber/inputnumber.tsx
+++ b/src/packages/inputnumber/inputnumber.tsx
@@ -24,7 +24,7 @@ export interface InputNumberProps extends BasicComponent {
formatter?: (value?: string | number) => string
onPlus: (e: React.MouseEvent) => void
onMinus: (e: React.MouseEvent) => void
- onOverlimit: (e: React.MouseEvent) => void
+ onOverlimit: (e: React.MouseEvent | ChangeEvent) => void
onBlur: (e: React.FocusEvent) => void
onFocus: (e: React.FocusEvent) => void
onChange: (
@@ -177,6 +177,24 @@ export const InputNumber: FunctionComponent<
if (text === '-') return null
return text
}
+ const clampValue = (valueStr: string | null) => {
+ if (valueStr === null) return defaultValue
+ const val = Number(parseFloat(valueStr || '0').toFixed(digits))
+ return Math.max(Number(min), Math.min(Number(max), val))
+ }
+ const handleValueChange = (
+ valueStr: string | null,
+ e: React.ChangeEvent
+ ) => {
+ const val = clampValue(valueStr)
+ // input暂不触发onOverlimit
+ // if (val !== Number(e.target.value)) {
+ // onOverlimit?.(e)
+ // }
+ if (val !== Number(shadowValue)) {
+ onChange?.(val, e)
+ }
+ }
const handleInputChange = (e: React.ChangeEvent) => {
// 设置 input 值, 在 blur 时格式化
setInputValue(e.target.value)
@@ -188,11 +206,9 @@ export const InputNumber: FunctionComponent<
setShadowValue(defaultValue)
}
} else {
- setShadowValue(valueStr as any)
- }
- if (!async) {
- onChange?.(parseFloat(valueStr || '0').toFixed(digits) as any, e)
+ setShadowValue(clampValue(valueStr) as any)
}
+ !async && handleValueChange(valueStr, e)
}
const handleFocus = (e: React.FocusEvent) => {
setFocused(true)
@@ -201,15 +217,22 @@ export const InputNumber: FunctionComponent<
? bound(Number(shadowValue), Number(min), Number(max)).toString()
: ''
)
- onFocus && onFocus(e)
+ onFocus?.(e)
}
const handleBlur = (e: React.FocusEvent) => {
setFocused(false)
- onBlur && onBlur(e)
- if (async) {
- const valueStr = parseValue(e.target.value)
- onChange?.(parseFloat(valueStr || '0').toFixed(digits) as any, e)
+ onBlur?.(e)
+ const valueStr = parseValue(e.target.value)
+ if (valueStr === null) {
+ if (allowEmpty) {
+ setShadowValue(null)
+ } else {
+ setShadowValue(defaultValue)
+ }
+ } else {
+ setShadowValue(clampValue(valueStr) as any)
}
+ async && handleValueChange(valueStr, e)
}
return (