Skip to content

Commit f099a9a

Browse files
(Picklist): reduce the number of unnecessary recalculation
1 parent 1d1e691 commit f099a9a

File tree

1 file changed

+11
-13
lines changed

1 file changed

+11
-13
lines changed

src/scripts/Picklist.tsx

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import React, {
1010
useState,
1111
useEffect,
1212
useCallback,
13+
useMemo,
1314
} from 'react';
1415
import classnames from 'classnames';
1516
import { FormElement, FormElementProps } from './FormElement';
@@ -260,15 +261,14 @@ export const Picklist: (<MultiSelect extends boolean | undefined>(
260261

261262
const { getActiveElement } = useContext(ComponentSettingsContext);
262263

263-
// Get option values from children (recursively)
264-
const getOptionValues = useCallback(() => {
264+
// Memoized option values - recursively collected from PicklistItem components (excluding disabled items)
265+
const optionValues = useMemo(() => {
265266
return collectOptionValues(children);
266267
}, [children]);
267268

268269
// Get next option value for keyboard navigation
269270
const getNextValue = useCallback(
270271
(currentValue?: PicklistValue) => {
271-
const optionValues = getOptionValues();
272272
if (optionValues.length === 0) return undefined;
273273

274274
if (!currentValue) return optionValues[0];
@@ -278,21 +278,20 @@ export const Picklist: (<MultiSelect extends boolean | undefined>(
278278
Math.min(currentIndex + 1, optionValues.length - 1)
279279
]; // not wrap around
280280
},
281-
[getOptionValues]
281+
[optionValues]
282282
);
283283

284284
// Get previous option value for keyboard navigation
285285
const getPrevValue = useCallback(
286286
(currentValue?: PicklistValue) => {
287-
const optionValues = getOptionValues();
288287
if (optionValues.length === 0) return undefined;
289288

290289
if (!currentValue) return optionValues[optionValues.length - 1];
291290

292291
const currentIndex = optionValues.indexOf(currentValue);
293292
return optionValues[Math.max(currentIndex - 1, 0)]; // not wrap around
294293
},
295-
[getOptionValues]
294+
[optionValues]
296295
);
297296

298297
// Scroll focused element into view
@@ -319,8 +318,7 @@ export const Picklist: (<MultiSelect extends boolean | undefined>(
319318
useEffect(() => {
320319
if (opened && !focusedValue) {
321320
// Focus on first selected value or first option
322-
const initialFocus =
323-
values.length > 0 ? values[0] : getOptionValues()[0];
321+
const initialFocus = values.length > 0 ? values[0] : optionValues[0];
324322
setFocusedValue(initialFocus);
325323
scrollFocusedElementIntoView(initialFocus);
326324
} else if (!opened) {
@@ -330,7 +328,7 @@ export const Picklist: (<MultiSelect extends boolean | undefined>(
330328
}, [
331329
opened,
332330
values,
333-
getOptionValues,
331+
optionValues,
334332
focusedValue,
335333
scrollFocusedElementIntoView,
336334
]);
@@ -438,7 +436,6 @@ export const Picklist: (<MultiSelect extends boolean | undefined>(
438436
if (opened) {
439437
e.preventDefault();
440438
e.stopPropagation();
441-
const optionValues = getOptionValues();
442439
const currentIndex = focusedValue
443440
? optionValues.indexOf(focusedValue)
444441
: -1;
@@ -487,7 +484,8 @@ export const Picklist: (<MultiSelect extends boolean | undefined>(
487484
onKeyDown_?.(e);
488485
});
489486

490-
function getSelectedItemLabel() {
487+
// Memoized selected item label - displays count for multiple selections, label for single selection, or placeholder text
488+
const selectedItemLabel = useMemo(() => {
491489
// many items selected
492490
if (values.length > 1) {
493491
return `${values.length} ${optionsSelectedText}`;
@@ -502,7 +500,7 @@ export const Picklist: (<MultiSelect extends boolean | undefined>(
502500

503501
// zero items
504502
return selectedText;
505-
}
503+
}, [values, optionsSelectedText, selectedText, children]);
506504

507505
const hasValue = values.length > 0;
508506
const containerClassNames = classnames(
@@ -577,7 +575,7 @@ export const Picklist: (<MultiSelect extends boolean | undefined>(
577575
onBlur={onBlur}
578576
{...rprops}
579577
>
580-
<span className='slds-truncate'>{getSelectedItemLabel()}</span>
578+
<span className='slds-truncate'>{selectedItemLabel}</span>
581579
</div>
582580
<span className='slds-icon_container slds-icon-utility-down slds-input__icon slds-input__icon_right'>
583581
<Icon

0 commit comments

Comments
 (0)