fix: help will shake in Form (#20886)

This commit is contained in:
二货机器人 2020-01-14 14:45:22 +08:00 committed by GitHub
parent 8bf66ce8be
commit 7a3cf0b93e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 19 deletions

View File

@ -42,6 +42,7 @@ const FormItemInput: React.FC<FormItemInputProps & FormItemInputMiscProps> = ({
prefixCls,
wrapperCol,
children,
help,
errors,
onDomErrorVisibleChange,
hasFeedback,
@ -63,7 +64,7 @@ const FormItemInput: React.FC<FormItemInputProps & FormItemInputMiscProps> = ({
onDomErrorVisibleChange(true);
}
forceUpdate({});
});
}, !!help);
const memoErrors = useMemo(
() => cacheErrors,

View File

@ -324,4 +324,24 @@ describe('Form', () => {
}
/* eslint-enable */
});
// https://github.com/ant-design/ant-design/issues/20813
it('should update help directly when provided', () => {
function App() {
const [message, updateMessage] = React.useState('');
return (
<Form>
<Form.Item label="hello" help={message}>
<Input />
</Form.Item>
<Button onClick={() => updateMessage('bamboo')} />
</Form>
);
}
const wrapper = mount(<App />);
wrapper.find('button').simulate('click');
expect(wrapper.find('.ant-form-item').first().hasClass('ant-form-item-with-help')).toBeTruthy();
expect(wrapper.find('.ant-form-item-explain').text()).toEqual('bamboo');
});
});

View File

@ -10,6 +10,7 @@ type InternalNamePath = (string | number)[];
export function useCacheErrors(
errors: React.ReactNode[],
changeTrigger: (visible: boolean) => void,
directly: boolean,
): [boolean, React.ReactNode[]] {
const cacheRef = React.useRef({
errors,
@ -18,27 +19,35 @@ export function useCacheErrors(
const [, forceUpdate] = React.useState({});
const update = () => {
const prevVisible = cacheRef.current.visible;
const newVisible = !!errors.length;
const prevErrors = cacheRef.current.errors;
cacheRef.current.errors = errors;
cacheRef.current.visible = newVisible;
if (prevVisible !== newVisible) {
changeTrigger(newVisible);
} else if (
prevErrors.length !== errors.length ||
prevErrors.some((prevErr, index) => prevErr !== errors[index])
) {
forceUpdate({});
}
};
React.useEffect(() => {
const timeout = setTimeout(() => {
const prevVisible = cacheRef.current.visible;
const newVisible = !!errors.length;
const prevErrors = cacheRef.current.errors;
cacheRef.current.errors = errors;
cacheRef.current.visible = newVisible;
if (prevVisible !== newVisible) {
changeTrigger(newVisible);
} else if (
prevErrors.length !== errors.length ||
prevErrors.some((prevErr, index) => prevErr !== errors[index])
) {
forceUpdate({});
}
}, 10);
return () => clearTimeout(timeout);
if (!directly) {
const timeout = setTimeout(update, 10);
return () => clearTimeout(timeout);
}
}, [errors]);
if (directly) {
update();
}
return [cacheRef.current.visible, cacheRef.current.errors];
}