Browse Source

fix(Input): should not have value prop on input after click toggle icon (#37900)

* fix(Input): should not have value prop on input when click toggle icon

* fix: 修改参数名

* fix: 修改传参
pull/38005/head
linxianxi 2 years ago
committed by GitHub
parent
commit
23285382f1
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 21
      components/input/Input.tsx
  2. 13
      components/input/Password.tsx
  3. 13
      components/input/__tests__/Password.test.tsx
  4. 32
      components/input/hooks/useRemovePasswordTimeout.ts

21
components/input/Input.tsx

@ -13,6 +13,7 @@ import { FormItemInputContext, NoFormStyle } from '../form/context';
import type { InputStatus } from '../_util/statusUtils';
import { getMergedStatus, getStatusClassNames } from '../_util/statusUtils';
import warning from '../_util/warning';
import useRemovePasswordTimeout from './hooks/useRemovePasswordTimeout';
import { hasPrefixSuffix } from './utils';
export interface InputFocusOptions extends FocusOptions {
@ -171,25 +172,7 @@ const Input = forwardRef<InputRef, InputProps>((props, ref) => {
}, [inputHasPrefixSuffix]);
// ===================== Remove Password value =====================
const removePasswordTimeoutRef = useRef<number[]>([]);
const removePasswordTimeout = () => {
removePasswordTimeoutRef.current.push(
window.setTimeout(() => {
if (
inputRef.current?.input &&
inputRef.current?.input.getAttribute('type') === 'password' &&
inputRef.current?.input.hasAttribute('value')
) {
inputRef.current?.input.removeAttribute('value');
}
}),
);
};
useEffect(() => {
removePasswordTimeout();
return () => removePasswordTimeoutRef.current.forEach(item => window.clearTimeout(item));
}, []);
const removePasswordTimeout = useRemovePasswordTimeout(inputRef, true);
const handleBlur = (e: React.FocusEvent<HTMLInputElement>) => {
removePasswordTimeout();

13
components/input/Password.tsx

@ -2,10 +2,12 @@ import EyeInvisibleOutlined from '@ant-design/icons/EyeInvisibleOutlined';
import EyeOutlined from '@ant-design/icons/EyeOutlined';
import classNames from 'classnames';
import omit from 'rc-util/lib/omit';
import { composeRef } from 'rc-util/lib/ref';
import * as React from 'react';
import { useState } from 'react';
import { useRef, useState } from 'react';
import type { ConfigConsumerProps } from '../config-provider';
import { ConfigConsumer } from '../config-provider';
import useRemovePasswordTimeout from './hooks/useRemovePasswordTimeout';
import type { InputProps, InputRef } from './Input';
import Input from './Input';
@ -26,12 +28,19 @@ const ActionMap: Record<string, string> = {
const Password = React.forwardRef<InputRef, PasswordProps>((props, ref) => {
const [visible, setVisible] = useState(false);
const inputRef = useRef<InputRef>(null);
// Remove Password value
const removePasswordTimeout = useRemovePasswordTimeout(inputRef);
const onVisibleChange = () => {
const { disabled } = props;
if (disabled) {
return;
}
if (visible) {
removePasswordTimeout();
}
setVisible(prevState => !prevState);
};
@ -87,7 +96,7 @@ const Password = React.forwardRef<InputRef, PasswordProps>((props, ref) => {
omittedProps.size = size;
}
return <Input ref={ref} {...omittedProps} />;
return <Input ref={composeRef(ref, inputRef)} {...omittedProps} />;
};
return <ConfigConsumer>{renderPassword}</ConfigConsumer>;

13
components/input/__tests__/Password.test.tsx

@ -108,4 +108,17 @@ describe('Input.Password', () => {
await sleep();
expect(container.querySelector('input')?.getAttribute('value')).toBeFalsy();
});
it('should not show value attribute in input element after toggle visibility', async () => {
const { container } = render(<Input.Password />);
fireEvent.change(container.querySelector('input')!, { target: { value: 'value' } });
await sleep();
expect(container.querySelector('input')?.getAttribute('value')).toBeFalsy();
fireEvent.click(container.querySelector('.ant-input-password-icon')!);
await sleep();
expect(container.querySelector('input')?.getAttribute('value')).toBeTruthy();
fireEvent.click(container.querySelector('.ant-input-password-icon')!);
await sleep();
expect(container.querySelector('input')?.getAttribute('value')).toBeFalsy();
});
});

32
components/input/hooks/useRemovePasswordTimeout.ts

@ -0,0 +1,32 @@
import { useEffect, useRef } from 'react';
import type { InputRef } from '../Input';
export default function useRemovePasswordTimeout(
inputRef: React.RefObject<InputRef>,
triggerOnMount?: boolean,
) {
const removePasswordTimeoutRef = useRef<number[]>([]);
const removePasswordTimeout = () => {
removePasswordTimeoutRef.current.push(
window.setTimeout(() => {
if (
inputRef.current?.input &&
inputRef.current?.input.getAttribute('type') === 'password' &&
inputRef.current?.input.hasAttribute('value')
) {
inputRef.current?.input.removeAttribute('value');
}
}),
);
};
useEffect(() => {
if (triggerOnMount) {
removePasswordTimeout();
}
return () => removePasswordTimeoutRef.current.forEach(item => window.clearTimeout(item));
}, []);
return removePasswordTimeout;
}
Loading…
Cancel
Save