mirror of
https://github.com/zhigang1992/react.git
synced 2026-05-16 08:29:44 +08:00
fix(input): always synchronize external value and ignore changes (#336)
* fix(input): always synchronize external value and ignore changes * feat(input): support imperative API to update
This commit is contained in:
@@ -67,7 +67,7 @@ const Input = React.forwardRef<HTMLInputElement, React.PropsWithChildren<InputPr
|
||||
const [selfValue, setSelfValue] = useState<string>(initialValue)
|
||||
const [hover, setHover] = useState<boolean>(false)
|
||||
const { heightRatio, fontSize } = useMemo(() => getSizes(size), [size])
|
||||
const showClearIcon = useMemo(() => clearable && selfValue !== '', [selfValue, clearable])
|
||||
const isControlledComponent = useMemo(() => value !== undefined, [value])
|
||||
const labelClasses = useMemo(() => (labelRight ? 'right-label' : label ? 'left-label' : ''), [
|
||||
label,
|
||||
labelRight,
|
||||
@@ -80,12 +80,12 @@ const Input = React.forwardRef<HTMLInputElement, React.PropsWithChildren<InputPr
|
||||
theme.palette,
|
||||
status,
|
||||
])
|
||||
|
||||
const changeHandler = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
if (disabled || readOnly) return
|
||||
setSelfValue(event.target.value)
|
||||
onChange && onChange(event)
|
||||
}
|
||||
|
||||
const clearHandler = (event: React.MouseEvent<HTMLDivElement>) => {
|
||||
setSelfValue('')
|
||||
onClearClick && onClearClick(event)
|
||||
@@ -121,9 +121,18 @@ const Input = React.forwardRef<HTMLInputElement, React.PropsWithChildren<InputPr
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (value === undefined) return
|
||||
setSelfValue(value)
|
||||
}, [value])
|
||||
if (isControlledComponent) {
|
||||
setSelfValue(value as string)
|
||||
}
|
||||
})
|
||||
|
||||
const controlledValue = isControlledComponent
|
||||
? { value: selfValue }
|
||||
: { defaultValue: initialValue }
|
||||
const inputProps = {
|
||||
...props,
|
||||
...controlledValue,
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="with-label">
|
||||
@@ -139,7 +148,6 @@ const Input = React.forwardRef<HTMLInputElement, React.PropsWithChildren<InputPr
|
||||
type="text"
|
||||
ref={inputRef}
|
||||
className={`${disabled ? 'disabled' : ''} ${iconClasses}`}
|
||||
value={selfValue}
|
||||
placeholder={placeholder}
|
||||
disabled={disabled}
|
||||
readOnly={readOnly}
|
||||
@@ -147,11 +155,11 @@ const Input = React.forwardRef<HTMLInputElement, React.PropsWithChildren<InputPr
|
||||
onBlur={blurHandler}
|
||||
onChange={changeHandler}
|
||||
autoComplete={autoComplete}
|
||||
{...props}
|
||||
{...inputProps}
|
||||
/>
|
||||
{clearable && (
|
||||
<InputClearIcon
|
||||
visible={showClearIcon}
|
||||
visible={Boolean(inputRef.current && inputRef.current.value !== '')}
|
||||
heightRatio={heightRatio}
|
||||
disabled={disabled || readOnly}
|
||||
onClick={clearHandler}
|
||||
|
||||
@@ -185,6 +185,28 @@ Retrieve text input from a user.
|
||||
`}
|
||||
/>
|
||||
|
||||
<Playground
|
||||
title="Imperative API"
|
||||
desc="Update component in an uncontrolled way."
|
||||
scope={{ Input, Spacer, Button }}
|
||||
code={`
|
||||
() => {
|
||||
const ref = React.useRef(null)
|
||||
const setChange = () => {
|
||||
ref && (ref.current.value = Math.random().toString(32))
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Input initialValue="Hello" onChange={e => console.log(e.target.value)} ref={ref} />
|
||||
<Spacer y={.5} />
|
||||
<Button auto type="secondary" size="small"
|
||||
onClick={setChange}>set value</Button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
`}
|
||||
/>
|
||||
|
||||
<Attributes edit="/pages/en-us/components/input.mdx">
|
||||
<Attributes.Title>Input.Props</Attributes.Title>
|
||||
|
||||
|
||||
@@ -186,6 +186,28 @@ export const meta = {
|
||||
`}
|
||||
/>
|
||||
|
||||
<Playground
|
||||
title="命令式 API"
|
||||
desc="使用非受控方式更新组件。"
|
||||
scope={{ Input, Spacer, Button }}
|
||||
code={`
|
||||
() => {
|
||||
const ref = React.useRef(null)
|
||||
const setChange = () => {
|
||||
ref && (ref.current.value = Math.random().toString(32))
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Input initialValue="Hello" onChange={e => console.log(e.target.value)} ref={ref} />
|
||||
<Spacer y={.5} />
|
||||
<Button auto type="secondary" size="small"
|
||||
onClick={setChange}>设置值</Button>
|
||||
</>
|
||||
)
|
||||
}
|
||||
`}
|
||||
/>
|
||||
|
||||
<Attributes edit="/pages/zh-cn/components/input.mdx">
|
||||
<Attributes.Title>Input.Props</Attributes.Title>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user