I am trying to eliminate this warning
MUI: The value provided to Autocomplete is invalid.
None of the options match with `""`.
You can use the `isOptionEqualToValue` prop to customize the equality test.
I go through a lot of Stack Overflow, it doesn't work. What am I missing here
const DropDownSearch = ({
setSelectedValue,
width = "auto",
label = "",
options = [],
defaultSelectedValue = "",
}) => {
console.log("🚀 DropDownInitiated ==", label);
const selectedVendorCode = setSelectedValue;
const [value, setValue] = useState(""); //selected value
const [inputValue, setInputValue] = useState(""); //user typing value/ display text
const [defaultValueIndex, setDefaultValueIndex] = useState(-1);
useEffect(() => {
// TODO: find default value index,
// TODO: to make selection as defualtValue
if (defaultSelectedValue.length > 0) {
const findIndex = options.findIndex(
(opt) => opt.value === defaultSelectedValue
);
console.log("findIndex =>>> ", findIndex);
setDefaultValueIndex(findIndex);
}
}, [defaultSelectedValue]);
useEffect(() => {
// TODO: once "useState value" (user selected value) changed,
// TODO: then send to parent component
if(value){
setSelectedValue?.(value);
}
}, [value]);
const optionData = useMemo(() => {
return options;
}, [options]);
const filterOptions = createFilterOptions({
stringify: (option) => {
return JSON.stringify(Object.values(option));
},
});
return (
<Autocomplete
defaultValue={
(defaultValueIndex >= 0) ? optionData[defaultValueIndex] : null
}
key={optionData.value}
isOptionEqualToValue={(option, value) => (value === undefined)? false : (option.value === '""')? false : option.value === value.value}
// {
// value ? option.value === value.value : false;
// if(!value) return false;
// if(value.value ==='""') return false;
// // console.log('option.value ==> ',option.value)
// // console.log(option)
// console.log('value.value ==> ',value.value)
// // console.log(value)
// return option.value === value.value;
// }}
filterOptions={filterOptions}
componentsProps={{ popper: { style: { width: "fit-content" } } }}
size="small"
id="dropdown-search"
value={value}
onChange={(event, newValue) => {
// TODO: set user selected value as OBJECT
setValue(newValue);
}}
inputValue={inputValue}
onInputChange={(event, newInputValue) => {
// TODO: this value is when user type on each key press
setInputValue(newInputValue);
}}
width={width}
options={optionData}
autoHighlight
/**
* ! renderOption
* this will show list of options, as a table format in dropdown list
*/
renderOption={(props, option, index) => (
<Box
component="li"
{...props}
style={{ display: "table-row" }}
sx={{ "& > img": { mr: 2, flexShrink: 0 } }}
key={JSON.stringify(Object.values(option))}
>
{Object.keys(option).map((key, index) => (
<div style={{ display: "table-cell", padding: "5px" }} key={index}>
{option[key]}
</div>
))}
</Box>
)}
renderInput={(params) => (
<TextField
{...params}
label={label}
inputProps={{ ...params.inputProps, autoComplete: "new-password" }}
/>
)}
/>
);
};
my dropdown list will host objects example:
options = [
{label:'xxx1',value:'yyy1'},
{label:'xxx2',value:'yyy2'}
]
I confirmed that there is no options.label or options.value = ""
I tried many things like below
this way
isOptionEqualToValue={(option, value) => option.value === value.value
also this
isOptionEqualToValue={(option, value) => {
if(!value) return false;
if(option.value ==="") return false;
if(option.value ==='""') return false;
if(value.value ==="") return false;
if(value.value ==='""') return false;
return option.value === value.value;
}}
You would not need some extra-complexity with isOptionEqualToValue. There is no need to define this property (neither the defaultValue one), and just set the non-selected value to null instead of an empty string ("").
Here is an example of a controlled Autocomplete implementation:
const options = [
{ label: "The Shawshank Redemption", value: 1 },
{ label: "The Godfather", value: 2 }
];
export default function AutocompleteComponent() {
// Value is null by default
const [value, setValue] = useState(null);
// Input value is an empty string by default
const [inputValue, setInputValue] = useState("");
return (
<Autocomplete
options={options}
value={value}
onChange={(event, newValue) => {
setValue(newValue);
}}
inputValue={inputValue}
onInputChange={(event, newInputValue) => {
setInputValue(newInputValue);
}}
renderInput={(params) => <TextField {...params} label="Movie" />}
/>
);
}
You can find a simplified working example on CodeSandbox.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With