Skip to content

Commit 00d1e81

Browse files
committed
Only memoize objects/arrays from props
1 parent 0cbdd5a commit 00d1e81

File tree

3 files changed

+90
-47
lines changed

3 files changed

+90
-47
lines changed

src/hooks/useCioAutocomplete.ts

+5-47
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ import { useMemo, useState } from 'react';
44
import useCioClient from './useCioClient';
55
import useDownShift from './useDownShift';
66
import {
7-
CioAutocompleteProps,
87
CioClientConfig,
98
Section,
109
UserDefinedSection,
1110
HTMLPropsWithCioDataAttributes,
1211
Item,
12+
UseCioAutocompleteOptions,
1313
} from '../types';
1414
import usePrevious from './usePrevious';
1515
import {
@@ -23,7 +23,8 @@ import {
2323
import useConsoleErrors from './useConsoleErrors';
2424
import useSections from './useSections';
2525
import useRecommendationsObserver from './useRecommendationsObserver';
26-
import { isAutocompleteSection, isCustomSection, isRecommendationsSection } from '../typeGuards';
26+
import { isCustomSection, isRecommendationsSection } from '../typeGuards';
27+
import useNormalizedProps from './useNormalizedProps';
2728

2829
export const defaultSections: UserDefinedSection[] = [
2930
{
@@ -36,65 +37,22 @@ export const defaultSections: UserDefinedSection[] = [
3637
},
3738
];
3839

39-
export type UseCioAutocompleteOptions = Omit<CioAutocompleteProps, 'children'>;
40-
41-
const convertLegacyParametersAndAddDefaults = (sections: UserDefinedSection[]) =>
42-
sections.map((config) => {
43-
if (isRecommendationsSection(config)) {
44-
if (config.identifier && !config.podId) {
45-
return { ...config, podId: config.identifier };
46-
}
47-
48-
if (!config.indexSectionName) {
49-
return { ...config, indexSectionName: 'Products' };
50-
}
51-
}
52-
53-
if (isAutocompleteSection(config)) {
54-
if (config.identifier && !config.indexSectionName) {
55-
return { ...config, indexSectionName: config.identifier };
56-
}
57-
}
58-
59-
return config;
60-
});
61-
6240
const useCioAutocomplete = (options: UseCioAutocompleteOptions) => {
41+
const { sections, zeroStateSections, cioJsClientOptions, advancedParameters } =
42+
useNormalizedProps(options);
6343
const {
6444
onSubmit,
6545
onChange,
6646
openOnFocus,
6747
apiKey,
6848
cioJsClient,
69-
cioJsClientOptions,
7049
placeholder = 'What can we help you find today?',
7150
autocompleteClassName = 'cio-autocomplete',
72-
advancedParameters,
7351
defaultInput,
7452
getSearchResultsUrl,
7553
onIsOpenChange,
7654
} = options;
7755

78-
let { sections = defaultSections, zeroStateSections } = options;
79-
80-
sections = useMemo(() => {
81-
if (sections) {
82-
return convertLegacyParametersAndAddDefaults(sections);
83-
}
84-
85-
return sections;
86-
// eslint-disable-next-line react-hooks/exhaustive-deps
87-
}, [JSON.stringify(sections)]);
88-
89-
zeroStateSections = useMemo(() => {
90-
if (zeroStateSections) {
91-
return convertLegacyParametersAndAddDefaults(zeroStateSections);
92-
}
93-
94-
return zeroStateSections;
95-
// eslint-disable-next-line react-hooks/exhaustive-deps
96-
}, [JSON.stringify(zeroStateSections)]);
97-
9856
const [query, setQuery] = useState(defaultInput || '');
9957
const previousQuery = usePrevious(query);
10058
const cioClient = useCioClient({ apiKey, cioJsClient, cioJsClientOptions } as CioClientConfig);

src/hooks/useNormalizedProps.ts

+83
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/* eslint-disable react-hooks/exhaustive-deps */
2+
import { useMemo } from 'react';
3+
import { UseCioAutocompleteOptions, UserDefinedSection } from '../types';
4+
import { isAutocompleteSection, isRecommendationsSection } from '../typeGuards';
5+
6+
export const defaultSections: UserDefinedSection[] = [
7+
{
8+
indexSectionName: 'Search Suggestions',
9+
type: 'autocomplete',
10+
},
11+
{
12+
indexSectionName: 'Products',
13+
type: 'autocomplete',
14+
},
15+
];
16+
17+
const convertLegacyParametersAndAddDefaults = (sections: UserDefinedSection[]) =>
18+
sections.map((config) => {
19+
if (isRecommendationsSection(config)) {
20+
if (config.identifier && !config.podId) {
21+
return { ...config, podId: config.identifier };
22+
}
23+
24+
if (!config.indexSectionName) {
25+
return { ...config, indexSectionName: 'Products' };
26+
}
27+
}
28+
29+
if (isAutocompleteSection(config)) {
30+
if (config.identifier && !config.indexSectionName) {
31+
return { ...config, indexSectionName: config.identifier };
32+
}
33+
}
34+
35+
return config;
36+
});
37+
38+
const normalizeSections = (sections: UserDefinedSection[] | undefined) => {
39+
if (sections) {
40+
return convertLegacyParametersAndAddDefaults(sections);
41+
}
42+
43+
return sections;
44+
};
45+
46+
// Normalize and Memoize Objects to prevent infinite rerenders if users pass object literals to useCioAutocomplete
47+
const useNormalizedProps = (options: UseCioAutocompleteOptions) => {
48+
const {
49+
sections = defaultSections,
50+
zeroStateSections,
51+
cioJsClientOptions,
52+
advancedParameters,
53+
} = options;
54+
55+
const sectionsMemoized = useMemo(
56+
() => normalizeSections(sections),
57+
[JSON.stringify(sections)]
58+
) as UserDefinedSection[];
59+
60+
const zeroStateSectionsMemoized = useMemo(
61+
() => normalizeSections(zeroStateSections),
62+
[JSON.stringify(zeroStateSections)]
63+
);
64+
65+
const cioJsClientOptionsMemoized = useMemo(
66+
() => cioJsClientOptions,
67+
[JSON.stringify(cioJsClientOptions)]
68+
);
69+
70+
const advancedParametersMemoized = useMemo(
71+
() => advancedParameters,
72+
[JSON.stringify(advancedParameters)]
73+
);
74+
75+
return {
76+
sections: sectionsMemoized,
77+
zeroStateSections: zeroStateSectionsMemoized,
78+
cioJsClientOptions: cioJsClientOptionsMemoized,
79+
advancedParameters: advancedParametersMemoized,
80+
};
81+
};
82+
83+
export default useNormalizedProps;

src/types.ts

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ export type CioAutocompleteProps = CioClientConfig & {
5050
defaultInput?: string;
5151
};
5252

53+
export type UseCioAutocompleteOptions = Omit<CioAutocompleteProps, 'children'>;
54+
5355
/**
5456
* AutocompleteSubmitEvent type is AutocompleteSelectSubmit or AutocompleteSearchSubmit.
5557
* Use isAutocompleteSearchSubmit or isAutocompleteSelectSubmit type predicates to safely access event properties.

0 commit comments

Comments
 (0)