fix: Transfer dataSource cannot be immutable (#28675)

close #28662
This commit is contained in:
偏右 2021-01-04 18:33:31 +08:00 committed by GitHub
parent 3ac343333a
commit 7def9de31d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 266 additions and 3 deletions

View File

@ -1013,3 +1013,248 @@ exports[`Transfer should support render value and label in item 1`] = `
</div>
</div>
`;
exports[`immutable data dataSource is frozen 1`] = `
<div
class="ant-transfer"
>
<div
class="ant-transfer-list"
>
<div
class="ant-transfer-list-header"
>
<label
class="ant-checkbox-wrapper"
>
<span
class="ant-checkbox"
>
<input
class="ant-checkbox-input"
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
aria-label="down"
class="anticon anticon-down ant-dropdown-trigger ant-transfer-list-header-dropdown"
role="img"
>
<svg
aria-hidden="true"
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
/>
</svg>
</span>
<span
class="ant-transfer-list-header-selected"
>
1 item
</span>
<span
class="ant-transfer-list-header-title"
/>
</div>
<div
class="ant-transfer-list-body"
>
<ul
class="ant-transfer-list-content"
>
<li
class="ant-transfer-list-content-item"
>
<label
class="ant-checkbox-wrapper"
>
<span
class="ant-checkbox"
>
<input
class="ant-checkbox-input"
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
class="ant-transfer-list-content-item-text"
/>
</li>
</ul>
</div>
</div>
<div
class="ant-transfer-operation"
>
<button
class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only"
disabled=""
type="button"
>
<span
aria-label="right"
class="anticon anticon-right"
role="img"
>
<svg
aria-hidden="true"
data-icon="right"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M765.7 486.8L314.9 134.7A7.97 7.97 0 00302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 000-50.4z"
/>
</svg>
</span>
</button>
<button
class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only"
disabled=""
type="button"
>
<span
aria-label="left"
class="anticon anticon-left"
role="img"
>
<svg
aria-hidden="true"
data-icon="left"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M724 218.3V141c0-6.7-7.7-10.4-12.9-6.3L260.3 486.8a31.86 31.86 0 000 50.3l450.8 352.1c5.3 4.1 12.9.4 12.9-6.3v-77.3c0-4.9-2.3-9.6-6.1-12.6l-360-281 360-281.1c3.8-3 6.1-7.7 6.1-12.6z"
/>
</svg>
</span>
</button>
</div>
<div
class="ant-transfer-list"
>
<div
class="ant-transfer-list-header"
>
<label
class="ant-checkbox-wrapper"
>
<span
class="ant-checkbox"
>
<input
class="ant-checkbox-input"
type="checkbox"
/>
<span
class="ant-checkbox-inner"
/>
</span>
</label>
<span
aria-label="down"
class="anticon anticon-down ant-dropdown-trigger ant-transfer-list-header-dropdown"
role="img"
>
<svg
aria-hidden="true"
data-icon="down"
fill="currentColor"
focusable="false"
height="1em"
viewBox="64 64 896 896"
width="1em"
>
<path
d="M884 256h-75c-5.1 0-9.9 2.5-12.9 6.6L512 654.2 227.9 262.6c-3-4.1-7.8-6.6-12.9-6.6h-75c-6.5 0-10.3 7.4-6.5 12.7l352.6 486.1c12.8 17.6 39 17.6 51.7 0l352.6-486.1c3.9-5.3.1-12.7-6.4-12.7z"
/>
</svg>
</span>
<span
class="ant-transfer-list-header-selected"
>
0 item
</span>
<span
class="ant-transfer-list-header-title"
/>
</div>
<div
class="ant-transfer-list-body"
>
<div
class="ant-transfer-list-body-not-found"
>
<div
class="ant-empty ant-empty-normal ant-empty-small"
>
<div
class="ant-empty-image"
>
<svg
class="ant-empty-img-simple"
height="41"
viewBox="0 0 64 41"
width="64"
xmlns="http://www.w3.org/2000/svg"
>
<g
fill="none"
fill-rule="evenodd"
transform="translate(0 1)"
>
<ellipse
class="ant-empty-img-simple-ellipse"
cx="32"
cy="33"
rx="32"
ry="7"
/>
<g
class="ant-empty-img-simple-g"
fill-rule="nonzero"
>
<path
d="M55 12.76L44.854 1.258C44.367.474 43.656 0 42.907 0H21.093c-.749 0-1.46.474-1.947 1.257L9 12.761V22h46v-9.24z"
/>
<path
class="ant-empty-img-simple-path"
d="M41.613 15.931c0-1.605.994-2.93 2.227-2.931H55v18.137C55 33.26 53.68 35 52.05 35h-40.1C10.32 35 9 33.259 9 31.137V13h11.16c1.233 0 2.227 1.323 2.227 2.928v.022c0 1.605 1.005 2.901 2.237 2.901h14.752c1.232 0 2.237-1.308 2.237-2.913v-.007z"
/>
</g>
</g>
</svg>
</div>
<p
class="ant-empty-description"
>
No Data
</p>
</div>
</div>
</div>
</div>
</div>
`;

View File

@ -543,3 +543,18 @@ describe('Transfer', () => {
expect(onChange).toHaveBeenCalledWith([], 'left', ['b']);
});
});
describe('immutable data', () => {
// https://github.com/ant-design/ant-design/issues/28662
it('dataSource is frozen', () => {
const mockData = [
Object.freeze({
id: 0,
title: `title`,
description: `description`,
}),
];
const wrapper = mount(<Transfer rowKey={item => item.id} dataSource={mockData} />);
expect(wrapper).toMatchRenderedSnapshot();
});
});

View File

@ -28,7 +28,7 @@ for (let i = 0; i < 20; i++) {
const initialTargetKeys = mockData.filter(item => +item.key > 10).map(item => item.key);
const App1 = () => {
const App = () => {
const [targetKeys, setTargetKeys] = useState(initialTargetKeys);
const [selectedKeys, setSelectedKeys] = useState([]);
const onChange = (nextTargetKeys, direction, moveKeys) => {
@ -63,5 +63,5 @@ const App1 = () => {
);
};
ReactDOM.render(<App1 />, mountNode);
ReactDOM.render(<App />, mountNode);
```

View File

@ -331,7 +331,10 @@ class Transfer<RecordType extends TransferItem = TransferItem> extends React.Com
const rightDataSource: KeyWise<RecordType>[] = new Array(targetKeys.length);
dataSource.forEach((record: KeyWise<RecordType>) => {
if (rowKey) {
record.key = rowKey(record);
record = {
...record,
key: rowKey(record),
};
}
// rightDataSource should be ordered by targetKeys