mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-18 06:03:38 +08:00
fix: Upload in React 18 sync problem (#36968)
* fix: sync flush * test: test case * test: fix deps
This commit is contained in:
parent
74d76038ad
commit
ad312b23a2
@ -3,6 +3,7 @@ import type { UploadProps as RcUploadProps } from 'rc-upload';
|
||||
import RcUpload from 'rc-upload';
|
||||
import useMergedState from 'rc-util/lib/hooks/useMergedState';
|
||||
import * as React from 'react';
|
||||
import { flushSync } from 'react-dom';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import DisabledContext from '../config-provider/DisabledContext';
|
||||
import LocaleReceiver from '../locale-provider/LocaleReceiver';
|
||||
@ -101,7 +102,11 @@ const InternalUpload: React.ForwardRefRenderFunction<unknown, UploadProps> = (pr
|
||||
cloneList = cloneList.slice(0, maxCount);
|
||||
}
|
||||
|
||||
setMergedFileList(cloneList);
|
||||
// Prevent React18 auto batch since input[upload] trigger process at same time
|
||||
// which makes fileList closure problem
|
||||
flushSync(() => {
|
||||
setMergedFileList(cloneList);
|
||||
});
|
||||
|
||||
const changeInfo: UploadChangeParam<UploadFile> = {
|
||||
file: file as UploadFile,
|
||||
|
@ -914,7 +914,7 @@ describe('Upload', () => {
|
||||
throw new TypeError("Object doesn't support this action");
|
||||
};
|
||||
|
||||
jest.spyOn(global, 'File').mockImplementationOnce(fileConstructor);
|
||||
const spyIE = jest.spyOn(global, 'File').mockImplementationOnce(fileConstructor);
|
||||
fireEvent.change(container.querySelector('input'), {
|
||||
target: {
|
||||
files: [{ file: 'foo.png' }],
|
||||
@ -925,6 +925,7 @@ describe('Upload', () => {
|
||||
await sleep();
|
||||
|
||||
expect(onChange.mock.calls[0][0].fileList).toHaveLength(1);
|
||||
spyIE.mockRestore();
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/33819
|
||||
@ -965,4 +966,58 @@ describe('Upload', () => {
|
||||
const { container: wrapper2 } = render(<Upload prefixCls="custom-upload" />);
|
||||
expect(wrapper2.querySelectorAll('.custom-upload-list').length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
// https://github.com/ant-design/ant-design/issues/36869
|
||||
it('Prevent auto batch', async () => {
|
||||
const mockFile1 = new File(['bamboo'], 'bamboo.png', {
|
||||
type: 'image/png',
|
||||
});
|
||||
const mockFile2 = new File(['light'], 'light.png', {
|
||||
type: 'image/png',
|
||||
});
|
||||
|
||||
let info1;
|
||||
let info2;
|
||||
|
||||
const onChange = jest.fn();
|
||||
const { container } = render(
|
||||
<Upload
|
||||
customRequest={info => {
|
||||
if (info.file === mockFile1) {
|
||||
info1 = info;
|
||||
} else {
|
||||
info2 = info;
|
||||
}
|
||||
}}
|
||||
onChange={onChange}
|
||||
/>,
|
||||
);
|
||||
|
||||
fireEvent.change(container.querySelector('input'), {
|
||||
target: {
|
||||
files: [mockFile1, mockFile2],
|
||||
},
|
||||
});
|
||||
|
||||
// React 18 is async now
|
||||
await act(async () => {
|
||||
await sleep();
|
||||
});
|
||||
onChange.mockReset();
|
||||
|
||||
// Processing
|
||||
act(() => {
|
||||
info1.onProgress({ percent: 10 }, mockFile1);
|
||||
info2.onProgress({ percent: 20 }, mockFile2);
|
||||
});
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
fileList: [
|
||||
expect.objectContaining({ percent: 10 }),
|
||||
expect.objectContaining({ percent: 20 }),
|
||||
],
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user