Skip to content

Commit cc728f3

Browse files
authored
chore: use useMemo to cache result (#439)
1 parent 835bfc2 commit cc728f3

File tree

5 files changed

+57
-47
lines changed

5 files changed

+57
-47
lines changed

examples/single-animation.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const Test = () => (
1919
defaultValue="lucy"
2020
style={{ width: 500 }}
2121
animation="slide-up"
22-
showSearch={false}
22+
showSearch
2323
onChange={onChange}
2424
>
2525
<Option value="jack">

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"classnames": "2.x",
4343
"rc-animate": "^2.10.0",
4444
"rc-trigger": "^4.0.0-alpha.4",
45-
"rc-util": "^4.11.0",
45+
"rc-util": "^4.17.0",
4646
"rc-virtual-list": "^0.0.0-alpha.25",
4747
"warning": "^4.0.3"
4848
},

src/OptionList.tsx

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as React from 'react';
22
import KeyCode from 'rc-util/lib/KeyCode';
3+
import useMemo from 'rc-util/lib/hooks/useMemo';
34
import classNames from 'classnames';
45
import List from 'rc-virtual-list';
56
import TransBtn from './TransBtn';
@@ -70,6 +71,12 @@ const OptionList: React.RefForwardingComponent<
7071
) => {
7172
const itemPrefixCls = `${prefixCls}-item`;
7273

74+
const memoFlattenOptions = useMemo(
75+
() => flattenOptions,
76+
[open, flattenOptions],
77+
(prev, next) => next[0] && prev[1] !== next[1],
78+
);
79+
7380
// =========================== List ===========================
7481
const listRef = React.useRef<List>(null);
7582

@@ -85,12 +92,12 @@ const OptionList: React.RefForwardingComponent<
8592

8693
// ========================== Active ==========================
8794
const getEnabledActiveIndex = (index: number, offset: number = 1): number => {
88-
const len = flattenOptions.length;
95+
const len = memoFlattenOptions.length;
8996

9097
for (let i = 0; i < len; i += 1) {
9198
const current = (index + i * offset + len) % len;
9299

93-
const { group, data } = flattenOptions[current];
100+
const { group, data } = memoFlattenOptions[current];
94101
if (!group && !(data as OptionData).disabled) {
95102
return current;
96103
}
@@ -99,12 +106,14 @@ const OptionList: React.RefForwardingComponent<
99106
return -1;
100107
};
101108

102-
const [activeIndex, setActiveIndex] = React.useState(() => getEnabledActiveIndex(0));
109+
const [activeIndex, setActiveIndex] = React.useState(() =>
110+
getEnabledActiveIndex(0),
111+
);
103112
const setActive = (index: number) => {
104113
setActiveIndex(index);
105114

106115
// Trigger active event
107-
const flattenItem = flattenOptions[index];
116+
const flattenItem = memoFlattenOptions[index];
108117
if (!flattenItem) {
109118
onActiveValue(null, -1);
110119
return;
@@ -115,14 +124,18 @@ const OptionList: React.RefForwardingComponent<
115124

116125
// Auto active first item when list length or searchValue changed
117126
React.useEffect(() => {
118-
setActive(defaultActiveFirstOption !== false ? getEnabledActiveIndex(0) : -1);
119-
}, [flattenOptions.length, searchValue]);
127+
setActive(
128+
defaultActiveFirstOption !== false ? getEnabledActiveIndex(0) : -1,
129+
);
130+
}, [memoFlattenOptions.length, searchValue]);
120131

121132
// Auto scroll to item position in single mode
122133
React.useEffect(() => {
123134
if (!multiple && open && values.size === 1) {
124135
const value: RawValueType = Array.from(values)[0];
125-
const index = flattenOptions.findIndex(({ data }) => (data as OptionData).value === value);
136+
const index = memoFlattenOptions.findIndex(
137+
({ data }) => (data as OptionData).value === value,
138+
);
126139
setActive(index);
127140
scrollIntoView(index);
128141
}
@@ -156,7 +169,10 @@ const OptionList: React.RefForwardingComponent<
156169
}
157170

158171
if (offset !== 0) {
159-
const nextActiveIndex = getEnabledActiveIndex(activeIndex + offset, offset);
172+
const nextActiveIndex = getEnabledActiveIndex(
173+
activeIndex + offset,
174+
offset,
175+
);
160176
scrollIntoView(nextActiveIndex);
161177
setActive(nextActiveIndex);
162178
}
@@ -167,7 +183,7 @@ const OptionList: React.RefForwardingComponent<
167183
// >>> Select
168184
case KeyCode.ENTER: {
169185
// value
170-
const item = flattenOptions[activeIndex];
186+
const item = memoFlattenOptions[activeIndex];
171187
if (item && !(item.data as OptionData).disabled) {
172188
onSelectValue((item.data as OptionData).value);
173189
} else {
@@ -191,7 +207,7 @@ const OptionList: React.RefForwardingComponent<
191207
}));
192208

193209
// ========================== Render ==========================
194-
if (flattenOptions.length === 0) {
210+
if (memoFlattenOptions.length === 0) {
195211
return (
196212
<div
197213
role="listbox"
@@ -205,26 +221,35 @@ const OptionList: React.RefForwardingComponent<
205221
}
206222

207223
function renderItem(index: number) {
208-
const item = flattenOptions[index];
224+
const item = memoFlattenOptions[index];
209225
const value = item && (item.data as OptionData).value;
210226
return item ? (
211-
<div key={index} role="option" id={`${id}_list_${index}`} aria-selected={values.has(value)}>
227+
<div
228+
key={index}
229+
role="option"
230+
id={`${id}_list_${index}`}
231+
aria-selected={values.has(value)}
232+
>
212233
{value}
213234
</div>
214235
) : null;
215236
}
216237

217238
return (
218239
<>
219-
<div role="listbox" id={`${id}_list`} style={{ height: 0, overflow: 'hidden' }}>
240+
<div
241+
role="listbox"
242+
id={`${id}_list`}
243+
style={{ height: 0, overflow: 'hidden' }}
244+
>
220245
{renderItem(activeIndex - 1)}
221246
{renderItem(activeIndex)}
222247
{renderItem(activeIndex + 1)}
223248
</div>
224249
<List<SelectFlattenOptionData>
225250
itemKey="key"
226251
ref={listRef}
227-
data={flattenOptions}
252+
data={memoFlattenOptions}
228253
height={height}
229254
itemHeight={itemHeight}
230255
fullHeight={false}
@@ -237,7 +262,9 @@ const OptionList: React.RefForwardingComponent<
237262
// Group
238263
if (group) {
239264
return (
240-
<div className={classNames(itemPrefixCls, `${itemPrefixCls}-group`)}>
265+
<div
266+
className={classNames(itemPrefixCls, `${itemPrefixCls}-group`)}
267+
>
241268
{label !== undefined ? label : key}
242269
</div>
243270
);
@@ -251,15 +278,18 @@ const OptionList: React.RefForwardingComponent<
251278
const optionPrefixCls = `${itemPrefixCls}-option`;
252279
const optionClassName = classNames(itemPrefixCls, optionPrefixCls, {
253280
[`${optionPrefixCls}-grouped`]: groupOption,
254-
[`${optionPrefixCls}-active`]: activeIndex === itemIndex && !disabled,
281+
[`${optionPrefixCls}-active`]:
282+
activeIndex === itemIndex && !disabled,
255283
[`${optionPrefixCls}-disabled`]: disabled,
256284
[`${optionPrefixCls}-selected`]: selected,
257285
});
258286

259287
const mergedLabel = childrenAsData ? children : label;
260288

261289
const iconVisible =
262-
!menuItemSelectedIcon || typeof menuItemSelectedIcon === 'function' || selected;
290+
!menuItemSelectedIcon ||
291+
typeof menuItemSelectedIcon === 'function' ||
292+
selected;
263293

264294
return (
265295
<div
@@ -279,7 +309,9 @@ const OptionList: React.RefForwardingComponent<
279309
}
280310
}}
281311
>
282-
<div className={`${optionPrefixCls}-content`}>{mergedLabel || value}</div>
312+
<div className={`${optionPrefixCls}-content`}>
313+
{mergedLabel || value}
314+
</div>
283315
{React.isValidElement(menuItemSelectedIcon) || selected}
284316
{iconVisible && (
285317
<TransBtn
@@ -298,9 +330,10 @@ const OptionList: React.RefForwardingComponent<
298330
);
299331
};
300332

301-
const RefOptionList = React.forwardRef<RefOptionListProps, OptionListProps<SelectOptionsType>>(
302-
OptionList,
303-
);
333+
const RefOptionList = React.forwardRef<
334+
RefOptionListProps,
335+
OptionListProps<SelectOptionsType>
336+
>(OptionList);
304337
RefOptionList.displayName = 'OptionList';
305338

306339
export default RefOptionList;

src/PopupContainer.tsx

Lines changed: 0 additions & 16 deletions
This file was deleted.

src/SelectTrigger.tsx

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import * as React from 'react';
22
import Trigger from 'rc-trigger';
33
import classNames from 'classnames';
44
import { RenderDOMFunc } from './interface';
5-
import PopupContainer from './PopupContainer';
65

76
const BUILT_IN_PLACEMENTS = {
87
bottomLeft: {
@@ -100,13 +99,7 @@ const SelectTrigger: React.RefForwardingComponent<
10099
builtinPlacements={BUILT_IN_PLACEMENTS}
101100
prefixCls={dropdownPrefixCls}
102101
popupTransitionName={mergedTransitionName}
103-
popup={
104-
<div ref={popupRef}>
105-
<PopupContainer visible={visible} dropdownRender={dropdownRender}>
106-
{popupNode}
107-
</PopupContainer>
108-
</div>
109-
}
102+
popup={<div ref={popupRef}>{popupNode}</div>}
110103
popupAlign={dropdownAlign}
111104
popupVisible={visible}
112105
getPopupContainer={getPopupContainer}

0 commit comments

Comments
 (0)