fix: Textarea blink on first mount (#37847)

* fix: Textarea blink on first mount

* chore: Update ts def

* test: Update test case

* chore: bump rc-mentions

* test: Update snapshot

* test: Update test case
This commit is contained in:
二货爱吃白萝卜 2022-10-04 23:31:32 +08:00 committed by GitHub
parent b110ff0293
commit c436bd6f4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 36 additions and 27 deletions

View File

@ -1,7 +1,7 @@
import classNames from 'classnames';
import type { TextAreaProps as RcTextAreaProps } from 'rc-textarea';
import RcTextArea from 'rc-textarea';
import type ResizableTextArea from 'rc-textarea/lib/ResizableTextArea';
import type { ResizableTextAreaRef } from 'rc-textarea/lib/ResizableTextArea';
import useMergedState from 'rc-util/lib/hooks/useMergedState';
import omit from 'rc-util/lib/omit';
import * as React from 'react';
@ -56,7 +56,7 @@ export interface TextAreaProps extends RcTextAreaProps {
export interface TextAreaRef {
focus: (options?: InputFocusOptions) => void;
blur: () => void;
resizableTextArea?: ResizableTextArea;
resizableTextArea?: ResizableTextAreaRef;
}
const TextArea = React.forwardRef<TextAreaRef, TextAreaProps>(

View File

@ -4928,6 +4928,7 @@ Array [
<textarea
class="ant-input"
placeholder="Autosize height based on content lines"
style="height: 0px; resize: none;"
/>,
<div
style="margin: 24px 0px;"
@ -4935,6 +4936,7 @@ Array [
<textarea
class="ant-input"
placeholder="Autosize height with minimum and maximum number of lines"
style="height: -24px; resize: none; min-height: -8px; max-height: -24px;"
/>,
<div
style="margin: 24px 0px;"
@ -4942,6 +4944,7 @@ Array [
<textarea
class="ant-input"
placeholder="Controlled autosize"
style="height: -20px; resize: none; min-height: -12px; max-height: -20px;"
/>,
]
`;

View File

@ -1145,6 +1145,7 @@ Array [
<textarea
class="ant-input"
placeholder="Autosize height based on content lines"
style="height: 0px; resize: none;"
/>,
<div
style="margin: 24px 0px;"
@ -1152,6 +1153,7 @@ Array [
<textarea
class="ant-input"
placeholder="Autosize height with minimum and maximum number of lines"
style="height: -24px; resize: none; min-height: -8px; max-height: -24px;"
/>,
<div
style="margin: 24px 0px;"
@ -1159,6 +1161,7 @@ Array [
<textarea
class="ant-input"
placeholder="Controlled autosize"
style="height: -20px; resize: none; min-height: -12px; max-height: -20px;"
/>,
]
`;

View File

@ -3,8 +3,8 @@ import type { ChangeEventHandler, TextareaHTMLAttributes } from 'react';
import React, { useState } from 'react';
import Input from '..';
import focusTest from '../../../tests/shared/focusTest';
import { fireEvent, waitFakeTimer, render, sleep, triggerResize, pureRender } from '../../../tests/utils';
import type { RenderOptions } from '../../../tests/utils';
import { fireEvent, render, sleep, triggerResize } from '../../../tests/utils';
import type { TextAreaRef } from '../TextArea';
const { TextArea } = Input;
@ -29,10 +29,13 @@ describe('TextArea', () => {
});
it('should auto calculate height according to content length', async () => {
jest.useFakeTimers();
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});
const ref = React.createRef<TextAreaRef>();
const onInternalAutoSize = jest.fn();
const genTextArea = (props = {}) => (
<TextArea
value=""
@ -41,27 +44,29 @@ describe('TextArea', () => {
wrap="off"
ref={ref}
{...props}
{...{ onInternalAutoSize }}
/>
);
const { container, rerender } = render(genTextArea());
const mockFunc = jest.spyOn(ref.current?.resizableTextArea!, 'resizeTextarea');
const { container, rerender } = pureRender(genTextArea());
await waitFakeTimer();
expect(onInternalAutoSize).toHaveBeenCalledTimes(1);
rerender(genTextArea({ value: '1111\n2222\n3333' }));
// wrapper.setProps({ value: '1111\n2222\n3333' });
await sleep(0);
expect(mockFunc).toHaveBeenCalledTimes(1);
await waitFakeTimer();
expect(onInternalAutoSize).toHaveBeenCalledTimes(2);
rerender(genTextArea({ value: '1111' }));
// wrapper.setProps({ value: '1111' });
await sleep(0);
expect(mockFunc).toHaveBeenCalledTimes(2);
await waitFakeTimer();
expect(onInternalAutoSize).toHaveBeenCalledTimes(3);
expect(container.querySelector('textarea')?.style.overflow).toBeFalsy();
expect(errorSpy).not.toHaveBeenCalled();
errorSpy.mockRestore();
jest.clearAllTimers();
jest.useRealTimers();
});
it('should support onPressEnter and onKeyDown', () => {
@ -188,14 +193,6 @@ describe('TextArea', () => {
});
});
it('when prop value not in this.props, resizeTextarea should be called', async () => {
const ref = React.createRef<TextAreaRef>();
const { container } = render(<TextArea aria-label="textarea" ref={ref} />);
const resizeTextarea = jest.spyOn(ref.current?.resizableTextArea!, 'resizeTextarea');
fireEvent.change(container.querySelector('textarea')!, { target: { value: 'test' } });
expect(resizeTextarea).toHaveBeenCalled();
});
it('handleKeyDown', () => {
const onPressEnter = jest.fn();
const onKeyDown = jest.fn();
@ -209,17 +206,21 @@ describe('TextArea', () => {
});
it('should trigger onResize', async () => {
jest.useFakeTimers();
const onResize = jest.fn();
const ref = React.createRef<TextAreaRef>();
render(<TextArea ref={ref} onResize={onResize} autoSize />);
await sleep(100);
const target = ref.current?.resizableTextArea?.textArea!;
triggerResize(target);
await Promise.resolve();
const { container } = render(<TextArea ref={ref} onResize={onResize} autoSize />);
await waitFakeTimer();
triggerResize(container.querySelector('textarea')!);
await waitFakeTimer();
expect(onResize).toHaveBeenCalledWith(
expect.objectContaining({ width: expect.any(Number), height: expect.any(Number) }),
);
jest.clearAllTimers();
jest.useRealTimers();
});
it('should works same as Input', () => {

View File

@ -20,6 +20,7 @@ exports[`renders ./components/mentions/demo/autoSize.md extend context correctly
<textarea
class="rc-textarea"
rows="1"
style="height: 0px; resize: none;"
/>
</div>
`;

View File

@ -20,6 +20,7 @@ exports[`renders ./components/mentions/demo/autoSize.md correctly 1`] = `
<textarea
class="rc-textarea"
rows="1"
style="height: 0px; resize: none;"
/>
</div>
`;

View File

@ -134,7 +134,7 @@
"rc-image": "~5.7.0",
"rc-input": "~0.1.2",
"rc-input-number": "~7.3.9",
"rc-mentions": "~1.9.1",
"rc-mentions": "~1.10.0",
"rc-menu": "~9.6.3",
"rc-motion": "^2.6.1",
"rc-notification": "~4.6.0",
@ -150,7 +150,7 @@
"rc-switch": "~3.2.0",
"rc-table": "~7.26.0",
"rc-tabs": "~12.1.0-alpha.1",
"rc-textarea": "~0.3.0",
"rc-textarea": "~0.4.3",
"rc-tooltip": "~5.2.0",
"rc-tree": "~5.7.0",
"rc-tree-select": "~5.5.0",