Skip to content

Commit e8d6c5a

Browse files
authored
refactor: Simplify Select single structure (#1195)
* chore: init * test: update test case
1 parent b23bfff commit e8d6c5a

File tree

5 files changed

+64
-76
lines changed

5 files changed

+64
-76
lines changed

src/SelectInput/Content/SingleContent.tsx

Lines changed: 42 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,53 +29,68 @@ const SingleContent = React.forwardRef<HTMLInputElement, SharedContentProps>(
2929
return showSearch ? searchValue : '';
3030
}, [combobox, activeValue, inputChanged, triggerOpen, searchValue, showSearch]);
3131

32-
// Extract option props, excluding label and value, and handle className/style merging
33-
const optionProps = React.useMemo(() => {
34-
const restProps: React.HTMLAttributes<HTMLDivElement> = {
35-
className: `${prefixCls}-content-value`,
36-
style: mergedSearchValue
37-
? {
38-
visibility: 'hidden',
39-
}
40-
: {},
41-
};
32+
const [optionClassName, optionStyle, optionTitle, hasOptionStyle] = React.useMemo(() => {
33+
let className: string | undefined;
34+
let style: React.CSSProperties | undefined;
35+
let titleValue: string | undefined;
4236

4337
if (displayValue && selectContext?.flattenOptions) {
4438
const option = selectContext.flattenOptions.find((opt) => opt.value === displayValue.value);
4539
if (option?.data) {
46-
const { className, style } = option.data;
47-
Object.assign(restProps, {
48-
title: getTitle(option.data),
49-
className: clsx(restProps.className, className),
50-
style: { ...restProps.style, ...style },
51-
});
40+
className = option.data.className;
41+
style = option.data.style;
42+
titleValue = getTitle(option.data);
5243
}
5344
}
5445

55-
if (displayValue && !restProps.title) {
56-
restProps.title = getTitle(displayValue);
46+
if (displayValue && !titleValue) {
47+
titleValue = getTitle(displayValue);
5748
}
5849

5950
if (rootTitle !== undefined) {
60-
restProps.title = rootTitle;
51+
titleValue = rootTitle;
6152
}
6253

63-
return restProps;
64-
}, [displayValue, selectContext?.flattenOptions, prefixCls, mergedSearchValue, rootTitle]);
54+
const nextHasStyle = !!className || !!style;
55+
56+
return [className, style, titleValue, nextHasStyle] as const;
57+
}, [displayValue, selectContext?.flattenOptions, rootTitle]);
6558

6659
React.useEffect(() => {
6760
if (combobox) {
6861
setInputChanged(false);
6962
}
7063
}, [combobox, activeValue]);
7164

65+
// ========================== Render ==========================
66+
// Render value
67+
const renderValue = displayValue ? (
68+
hasOptionStyle ? (
69+
<div
70+
className={clsx(`${prefixCls}-content-value`, optionClassName)}
71+
style={{
72+
...(mergedSearchValue ? { visibility: 'hidden' } : {}),
73+
...optionStyle,
74+
}}
75+
title={optionTitle}
76+
>
77+
{displayValue.label}
78+
</div>
79+
) : (
80+
displayValue.label
81+
)
82+
) : (
83+
<Placeholder show={!mergedSearchValue} />
84+
);
85+
86+
// Render
7287
return (
73-
<div className={clsx(`${prefixCls}-content`, classNames?.content)} style={styles?.content}>
74-
{displayValue ? (
75-
<div {...optionProps}>{displayValue.label}</div>
76-
) : (
77-
<Placeholder show={!mergedSearchValue} />
78-
)}
88+
<div
89+
className={clsx(`${prefixCls}-content`, classNames?.content)}
90+
style={styles?.content}
91+
title={hasOptionStyle ? undefined : optionTitle}
92+
>
93+
{renderValue}
7994
<Input
8095
ref={ref}
8196
{...inputProps}

tests/Select.test.tsx

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2011,7 +2011,7 @@ describe('Select.Basic', () => {
20112011
[undefined].forEach((value) => {
20122012
it(`to ${value}`, () => {
20132013
const { container, rerender } = render(<Select value="light" />);
2014-
expect(container.querySelector('.rc-select-content-value').textContent).toEqual('light');
2014+
expect(findSelection(container).textContent).toEqual('light');
20152015

20162016
rerender(<Select value={value} />);
20172017
expect(container.querySelector('.rc-select-content-value')).toBeFalsy();
@@ -2133,7 +2133,7 @@ describe('Select.Basic', () => {
21332133
toggleOpen(container);
21342134
selectItem(container, index);
21352135
expect(onChange).toHaveBeenCalledWith(value, expect.anything());
2136-
expect(container.querySelector('.rc-select-content-value').textContent).toEqual(showValue);
2136+
expect(findSelection(container).textContent).toEqual(showValue);
21372137
});
21382138

21392139
expect(errorSpy).toHaveBeenCalledWith(warningMessage);
@@ -2399,9 +2399,7 @@ describe('Select.Basic', () => {
23992399
<Select value="b" options={[{ label: 'bamboo', title: 'TitleBamboo', value: 'b' }]} />,
24002400
);
24012401

2402-
expect(container.querySelector('.rc-select-content-value').getAttribute('title')).toEqual(
2403-
'TitleBamboo',
2404-
);
2402+
expect(findSelection(container).getAttribute('title')).toEqual('TitleBamboo');
24052403
});
24062404

24072405
it('multiple', () => {
@@ -2455,17 +2453,15 @@ describe('Select.Basic', () => {
24552453
it('should support title', () => {
24562454
const { container: container1 } = render(<Select defaultValue="lucy" options={[]} />);
24572455
expect(container1.querySelector('.rc-select').getAttribute('title')).toBeFalsy();
2458-
expect(container1.querySelector('.rc-select-content-value').getAttribute('title')).toBe('lucy');
2456+
expect(findSelection(container1).getAttribute('title')).toBe('lucy');
24592457
const { container: container2 } = render(<Select defaultValue="lucy" options={[]} title="" />);
24602458
expect(container2.querySelector('.rc-select').getAttribute('title')).toBeFalsy();
2461-
expect(container2.querySelector('.rc-select-content-value').getAttribute('title')).toBe('');
2459+
expect(findSelection(container2).getAttribute('title')).toBe('');
24622460
const { container: container3 } = render(
24632461
<Select defaultValue="lucy" options={[]} title="title" />,
24642462
);
24652463
expect(container3.querySelector('.rc-select').getAttribute('title')).toBe('title');
2466-
expect(container3.querySelector('.rc-select-content-value').getAttribute('title')).toBe(
2467-
'title',
2468-
);
2464+
expect(findSelection(container3).getAttribute('title')).toBe('title');
24692465
});
24702466

24712467
it('scrollbar should be left position with rtl direction', () => {

tests/__snapshots__/Select.test.tsx.snap

Lines changed: 10 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -112,13 +112,9 @@ exports[`Select.Basic render renders aria-attributes correctly 1`] = `
112112
>
113113
<div
114114
class="antd-content"
115+
title="2"
115116
>
116-
<div
117-
class="antd-content-value"
118-
title="2"
119-
>
120-
2
121-
</div>
117+
2
122118
<input
123119
aria-autocomplete="list"
124120
aria-expanded="false"
@@ -147,13 +143,9 @@ exports[`Select.Basic render renders correctly 1`] = `
147143
>
148144
<div
149145
class="antd-content"
146+
title="2"
150147
>
151-
<div
152-
class="antd-content-value"
153-
title="2"
154-
>
155-
2
156-
</div>
148+
2
157149
<input
158150
aria-autocomplete="list"
159151
aria-expanded="false"
@@ -182,13 +174,9 @@ exports[`Select.Basic render renders data-attributes correctly 1`] = `
182174
>
183175
<div
184176
class="antd-content"
177+
title="2"
185178
>
186-
<div
187-
class="antd-content-value"
188-
title="2"
189-
>
190-
2
191-
</div>
179+
2
192180
<input
193181
aria-autocomplete="list"
194182
aria-expanded="false"
@@ -215,13 +203,9 @@ exports[`Select.Basic render renders disabled select correctly 1`] = `
215203
>
216204
<div
217205
class="antd-content"
206+
title="2"
218207
>
219-
<div
220-
class="antd-content-value"
221-
title="2"
222-
>
223-
2
224-
</div>
208+
2
225209
<input
226210
aria-autocomplete="list"
227211
aria-expanded="false"
@@ -246,13 +230,9 @@ exports[`Select.Basic render renders role prop correctly 1`] = `
246230
>
247231
<div
248232
class="antd-content"
233+
title="2"
249234
>
250-
<div
251-
class="antd-content-value"
252-
title="2"
253-
>
254-
2
255-
</div>
235+
2
256236
<input
257237
aria-autocomplete="list"
258238
aria-expanded="false"

tests/placeholder.test.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import React from 'react';
22
import Select from '../src';
3-
import { toggleOpen } from './utils/common';
3+
import { toggleOpen, findSelection } from './utils/common';
44
import { render } from '@testing-library/react';
55

66
describe('Select placeholder', () => {
@@ -26,9 +26,9 @@ describe('Select placeholder', () => {
2626
<Select value={null} placeholder="bamboo" options={[{ value: null, label: 'light' }]} />,
2727
);
2828
expect(container.querySelector('.rc-select-placeholder')).toBeFalsy();
29-
expect(container.querySelector('.rc-select-content-value').textContent).toBe('light');
29+
expect(findSelection(container).textContent).toBe('light');
3030
toggleOpen(container);
31-
expect(container.querySelector('.rc-select-content-value').textContent).toBe('light');
31+
expect(findSelection(container).textContent).toBe('light');
3232
});
3333

3434
it('should hide placeholder if force closed and showSearch with searchValue', () => {

tests/utils/common.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ export function findSelection(wrapper: any, index: number = 0) {
4646
const itemNode = wrapper.querySelectorAll('.rc-select-selection-item')[index];
4747
const contentNode =
4848
itemNode?.querySelector('.rc-select-selection-item-content') ||
49-
wrapper.querySelector('.rc-select-content-value');
49+
wrapper.querySelector('.rc-select-content-value') ||
50+
wrapper.querySelector('.rc-select-content');
5051

5152
if (contentNode) {
5253
return contentNode;
@@ -110,11 +111,7 @@ export function injectRunAllTimers(jest: Jest) {
110111
});
111112
}
112113

113-
export function keyDown(
114-
element: HTMLElement,
115-
keyCode: number,
116-
options?: Partial<KeyboardEvent>,
117-
) {
114+
export function keyDown(element: HTMLElement, keyCode: number, options?: Partial<KeyboardEvent>) {
118115
const event = createEvent.keyDown(element, { keyCode, ...options });
119116
Object.defineProperties(event, {
120117
which: { get: () => keyCode },

0 commit comments

Comments
 (0)