Skip to content

Commit 8a4eaf6

Browse files
[Autocomplete] Prevent shrink animation in uncontrolled Autocomplete when default value is set (#44873)
1 parent 819e662 commit 8a4eaf6

File tree

2 files changed

+36
-10
lines changed

2 files changed

+36
-10
lines changed

packages/mui-material/src/useAutocomplete/useAutocomplete.js

+16-10
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ const defaultIsActiveElementInListbox = (listboxRef) =>
6161

6262
const MULTIPLE_DEFAULT_VALUE = [];
6363

64+
function getInputValue(value, multiple, getOptionLabel) {
65+
if (multiple || value == null) {
66+
return '';
67+
}
68+
const optionLabel = getOptionLabel(value);
69+
return typeof optionLabel === 'string' ? optionLabel : '';
70+
}
71+
6472
function useAutocomplete(props) {
6573
const {
6674
// eslint-disable-next-line @typescript-eslint/naming-convention
@@ -137,14 +145,20 @@ function useAutocomplete(props) {
137145
const defaultHighlighted = autoHighlight ? 0 : -1;
138146
const highlightedIndexRef = React.useRef(defaultHighlighted);
139147

148+
// Calculate the initial inputValue on mount only.
149+
// Using useRef since defaultValue doesn't need to update inputValue dynamically.
150+
const initialInputValue = React.useRef(
151+
getInputValue(defaultValue, multiple, getOptionLabel),
152+
).current;
153+
140154
const [value, setValueState] = useControlled({
141155
controlled: valueProp,
142156
default: defaultValue,
143157
name: componentName,
144158
});
145159
const [inputValue, setInputValueState] = useControlled({
146160
controlled: inputValueProp,
147-
default: '',
161+
default: initialInputValue,
148162
name: componentName,
149163
state: 'inputValue',
150164
});
@@ -159,15 +173,7 @@ function useAutocomplete(props) {
159173
if (!isOptionSelected && !clearOnBlur) {
160174
return;
161175
}
162-
let newInputValue;
163-
if (multiple) {
164-
newInputValue = '';
165-
} else if (newValue == null) {
166-
newInputValue = '';
167-
} else {
168-
const optionLabel = getOptionLabel(newValue);
169-
newInputValue = typeof optionLabel === 'string' ? optionLabel : '';
170-
}
176+
const newInputValue = getInputValue(newValue, multiple, getOptionLabel);
171177

172178
if (inputValue === newInputValue) {
173179
return;

packages/mui-material/src/useAutocomplete/useAutocomplete.test.js

+20
Original file line numberDiff line numberDiff line change
@@ -395,4 +395,24 @@ describe('useAutocomplete', () => {
395395
fireEvent.click(button);
396396
}).not.to.throw();
397397
});
398+
399+
describe('prop: defaultValue', () => {
400+
it('should not trigger onInputChange when defaultValue is provided', () => {
401+
const onInputChange = spy();
402+
const defaultValue = 'foo';
403+
404+
function Test() {
405+
const { getInputProps } = useAutocomplete({
406+
defaultValue,
407+
onInputChange,
408+
options: ['foo', 'bar'],
409+
});
410+
411+
return <input {...getInputProps()} />;
412+
}
413+
414+
render(<Test />);
415+
expect(onInputChange.callCount).to.equal(0);
416+
});
417+
});
398418
});

0 commit comments

Comments
 (0)