You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[autocomplete] getOptionLabel callback is getting the value instead of option object #31192
I'm expecting getOptionLabel method always passed an Option type but that's not the case. That's why the picked option can not be displayed properly.
getOptionLabel={(option)=>option.label||"!!!"}//here sometimes Value type is passes instead of Option type.isOptionEqualToValue={(option,value)=>returnoption.value===value}
Expected behavior 🤔
Always pass and option to getOptionLabel as a param to be consistent.
Render a controlled Autocomplete component using different types for options and value props. (object and string)
Utilize isOptionEqualToValue and getOptionLabel callback props
Context 🔦
I'm trying to render options that are objects like {label:"Label", value:"some value"}, but I want to use the value of the selected option instead of the whole option object.
Your environment 🌎
No response
Reacted by S4Mi, Baky Yegengeldiyev, WanYingT, lovervoorde, Neli Harbuzava, Olivier Tassinari, Roberto Baglieri, John Clary, msaad, Cristopher Dávila and 4 more
changed the title [-][Autocomplete] getOptionLabel callback is getting the value instead of option object[/-][+][Autocomplete] `getOptionLabel` callback is getting the value instead of option object[/+]on Feb 28, 2022
Why do you want to have value as a string? You can keep the value as one of the option object in the state if your options are objects.
Context 🔦
I'm trying to render options that are objects like {label:"Label", value:"some value"}, but I want to use the value of the selected option instead of the whole option object.
For my use-case, I wanted to have the option as a string because my onChange uses the value to update an object in redux state, and I don't want the label in there as well.
Reacted by Toni Hutter, Zirafnik, hasan-aa, John Clary, Gaurav Ramanan, Philipp Bisson and Alexandre Teyar
Why was this closed and the suggested PR just rejected?
I spent 2 days debugging what was breaking, only to find that getOptionLabel uses the value property to determine the text (label) for displaying selected option.
Assuming I have an array of objects as options, for instance [ { name: 'Charles Dickens', value: 'charles-dickens' } ]. I want to display the name property as label getOptionLabel={(option) => option.name} and save only the value to state, to be later sent to the backend onChange={(e, value) => setValue(value.value)}. In this case isOptionEqualToValue={(option, value) => option.value === value}.
Why am I therefore forced to save the whole object as the value? (just so getOptionLabel can then pull it to display selected value)
Reacted by hasan-aa, Neli Harbuzava, Jason Jose, Ben Gerdemann, John Clary, ian lyons, Jarek Ucinski, Parag-Evince, Angel Svirkov, Seyed Sina Pezeshk and 4 more
To support this request, I am using MUI with react-hook-form in which value from the server is in form of uuid (string) type and send the data back to the server with uuid (string) only.
If this issue is not tackled, I will need to either:
Convert uuid to full object as value to be compatible with the types, and then extract uuid from the full object when sending update request to the server.
Forcing a lot of types to work with having different types of value and option as in getOptionLabelisOptionEqualToValue etc.
Both took a lot of work and are prone to errors
I think the concept that value and option is separated is beneficial, while you can choose whether it is the same thing or not. This behavior is similar to Select component in which the options and value are separated.
A value must have the same type as an element of options. To solve your problem, I'd go with something like this:
// outside of the component:typeOption={value: string,name: string};constoptions: Option[]=[{name: 'Charles Dickens',value: 'charles-dickens'}]// in component:constvalues=React.useMemo(()=>options.map(o=>o.value));functiongetLabel(value){returnoptions.find(o=>o.value===value);}return(<Autocompleteoptions={values}getOptionLabel={getLabel}...
Would this solve your problem?
Having separate types for options and value would require more changes than what's proposed in #32439. The Autocomplete types assume that options: ReadonlyArray<T>; (where T is the type of the value)
Reacted by Zirafnik, Neli Harbuzava, Roberto Baglieri, Ben Gerdemann and Jonathan Higdon
I think at least a note should be added to the documentation of getOptionLabel method until this is fixed. The name suggests that it'll pass an option object.
There are ways to work around this but it's time consuming to debug and find the actual reason once you get that point.
Reacted by Zirafnik, Neli Harbuzava, M. Casey and Alexandre Teyar
@michaldudak Yes, but what we are saying is that this should not be the case. Value should not have to equal the option type. Value should be decoupled from options.
Obviously there are various workarounds for this at the moment, the easiest one being just saving 2 states: one for saving the actual chosen object (option) & the other for saving only the value that will be sent to the backend (option.value).
According to @Bearfinn this is already the implemented (and expected) behavior in the Select component, so it does not make sense for it to differ in Autocomplete. Until then I agree with the fact that this should be mentioned in docs (to save some people the trouble of debugging this unexpected behavior).
Reacted by Tammy Chu, Neli Harbuzava, ian lyons and Alexandre Teyar
Considering these words in the doc we expect that a bunch of string value + isOptionEqualToValue={(option, value) => option.value === value} + getOptionLabel={(option) => option.label} should work. But it doesn't.
Should be: either make getOptionLabel to get an option, either change this lines in the docs.
One case where this breaks is when the field is cleared. In this case, the value is "", which is never T in the case that options are some non-string object. So getOptionLabel receives "", but its option argument is not typed as T | string, it's typed as T.
Why is getOptionLabel called in this situation in the first place? There is no option selected, so there is no way to get its label.
I am having a similar issue with the argument in the call back however this is when the value in the option object is an array, it is only giving me the array.
if option 1 is selected I am getting ["ABC", "DEF"] as the argument in getOptionLabel and not { id: 1, label: 'option 1', value: [ "ABC", 'DEF']} as I would expect from the api docs.
I have workaround it for now but is is a little weird that the option object does exist in the correct shape to the spec. The workaround is a little inefficient as it means running a find on the available options again to get the label so would like to remove it.
Reacted by Roberto Baglieri, M. Casey, alejandraquimi, Dhruvil Prajapati, ProVival and Gaurav Ramanan
My case:
I have the form with autocomplete field on it. If i open the form to edit, i already have initial autocomplete value which comes form api and it is id.
autocomplete options: [{id: '1', name: 'option 1'}, {id: '2, name: 'option 2'}]
autocomplete value: '1'
I expect to see correct name in Autocomplete input field , not undefined, because i define getOptionLabel and assume that option parameter is option and not value
why value should have the same type as option if there is isOptionEqualToValue where i can say how value should be mapped to option.
based on the documentation, I would never have guessed that the 'label' in getOptionLabel is from 'values' and not from 'options'.
I expect that the list of options is there to get information about options from it.
Moreover, as mentioned above, when using a react-hook-form we have to work around it by keeping an eye on everything in many places at the same time, where if it worked in accordance with the above proposal, it would solve many problems.
Like if you use react-query for getting options, and react-hook-form for now I would need to reset form/field on every available options update.
Reacted by msaad, BLTHDJ, Mirza and Alexandre Teyar
Agreed with everyone here and specifically @alenadvainova 's point
why value should have the same type as option if there is isOptionEqualToValue where i can say how value should be mapped to option.
Converting the string back into an array using Array.find() might seem as a simple workaround, but for my case I have an Array of over 200,000 elements being efficiently searched locally by Orama in an Table of <Autocomplete>s
As you can empathise, any extra Array.find is a performance nuisance!
@ZeeshanTamboli@michaldudak As many others have mentioned, isOptionEqualToValue works in this case, so I think the issue should be resolved with a change in the type definitions only?
@michaldudak@ZeeshanTamboli still waiting on this, the getOptionLabel should have the selected option rather than the value to decouple the processed value from the displayed label. For instance, I do send the id only to my backend but display the name of the object. Right now this is a pain to get this working with autocomplete, by using the options as primary source for the autocomplete as opposed to the value that would solve the issue.
I don't think there are plans to update the existing Autocomplete before switching the implementation to Base UI's Combobox (@aarongarciah, correct me if I'm wrong).
changed the title [-][Autocomplete] `getOptionLabel` callback is getting the value instead of option object[/-][+][autocomplete] `getOptionLabel` callback is getting the value instead of option object[/+]on Mar 1, 2025
Activity
[-][Autocomplete] getOptionLabel callback is getting the value instead of option object[/-][+][Autocomplete] `getOptionLabel` callback is getting the value instead of option object[/+]ZeeshanTamboli commentedon Apr 28, 2022
Hi @hasan-aa ,
Why do you want to have
valueas a string? You can keep the value as one of the option object in the state if your options are objects.You can use the value of the selected option. See the following CodeSandbox: https://codesandbox.io/s/controllablestates-material-demo-forked-c4fw5y?file=/demo.js
lovervoorde commentedon Apr 28, 2022
For my use-case, I wanted to have the option as a string because my onChange uses the value to update an object in redux state, and I don't want the label in there as well.
Zirafnik commentedon Nov 9, 2022
Why was this closed and the suggested PR just rejected?
I spent 2 days debugging what was breaking, only to find that
getOptionLabeluses thevalueproperty to determine the text (label) for displaying selected option.Assuming I have an array of objects as
options, for instance[ { name: 'Charles Dickens', value: 'charles-dickens' } ]. I want to display thenameproperty as labelgetOptionLabel={(option) => option.name}and save only the value to state, to be later sent to the backendonChange={(e, value) => setValue(value.value)}. In this caseisOptionEqualToValue={(option, value) => option.value === value}.Why am I therefore forced to save the whole object as the value? (just so
getOptionLabelcan then pull it to display selected value)The fix linked above should be reconsidered.
ZeeshanTamboli commentedon Nov 11, 2022
Okay I am re-opening the PR.
Bearfinn commentedon Nov 17, 2022
To support this request, I am using MUI with
react-hook-formin whichvaluefrom the server is in form of uuid (string) type and send the data back to the server with uuid (string) only.If this issue is not tackled, I will need to either:
getOptionLabelisOptionEqualToValueetc.Both took a lot of work and are prone to errors
I think the concept that
valueandoptionis separated is beneficial, while you can choose whether it is the same thing or not. This behavior is similar toSelectcomponent in which the options and value are separated.michaldudak commentedon Nov 25, 2022
A
valuemust have the same type as an element ofoptions. To solve your problem, I'd go with something like this:Would this solve your problem?
Having separate types for
optionsandvaluewould require more changes than what's proposed in #32439. The Autocomplete types assume thatoptions: ReadonlyArray<T>;(whereTis the type of the value)hasan-aa commentedon Nov 25, 2022
I think at least a note should be added to the documentation of
getOptionLabelmethod until this is fixed. The name suggests that it'll pass an option object.There are ways to work around this but it's time consuming to debug and find the actual reason once you get that point.
Zirafnik commentedon Nov 25, 2022
@michaldudak Yes, but what we are saying is that this should not be the case. Value should not have to equal the option type. Value should be decoupled from options.
Obviously there are various workarounds for this at the moment, the easiest one being just saving 2 states: one for saving the actual chosen object (
option) & the other for saving only the value that will be sent to the backend (option.value).According to @Bearfinn this is already the implemented (and expected) behavior in the
Selectcomponent, so it does not make sense for it to differ inAutocomplete. Until then I agree with the fact that this should be mentioned in docs (to save some people the trouble of debugging this unexpected behavior).nelihabuzava commentedon Jan 6, 2023
The documentation is misleading:
Considering these words in the doc we expect that a bunch of string value +
isOptionEqualToValue={(option, value) => option.value === value}+getOptionLabel={(option) => option.label}should work. But it doesn't.Should be: either make
getOptionLabelto get anoption, either change this lines in the docs.4 remaining items
markedwards commentedon Feb 1, 2023
One case where this breaks is when the field is cleared. In this case, the value is
"", which is neverTin the case that options are some non-string object. SogetOptionLabelreceives"", but itsoptionargument is not typed asT | string, it's typed asT.Why is
getOptionLabelcalled in this situation in the first place? There is no option selected, so there is no way to get its label.oliviertassinari commentedon Feb 9, 2023
This issue looks like a duplicate of #23708 but focus on the docs that is currently confusing.
cpdwyer commentedon Feb 10, 2023
I am having a similar issue with the argument in the call back however this is when the value in the option object is an array, it is only giving me the array.
I am running 5.11.2
e.g. options
[{ id: 1, label: 'option 1', value: [ "ABC", 'DEF']}, { id: 2, label: 'option 2', value: ['123', '456']}]if option 1 is selected I am getting ["ABC", "DEF"] as the argument in getOptionLabel and not { id: 1, label: 'option 1', value: [ "ABC", 'DEF']} as I would expect from the api docs.
I have workaround it for now but is is a little weird that the option object does exist in the correct shape to the spec. The workaround is a little inefficient as it means running a find on the available options again to get the label so would like to remove it.
alenadvainova commentedon Oct 25, 2023
I have the same issue.
My case:
I have the form with autocomplete field on it. If i open the form to edit, i already have initial autocomplete value which comes form api and it is id.
autocomplete options: [{id: '1', name: 'option 1'}, {id: '2, name: 'option 2'}]
autocomplete value: '1'
I expect to see correct name in Autocomplete input field , not undefined, because i define getOptionLabel and assume that option parameter is option and not value
why value should have the same type as option if there is isOptionEqualToValue where i can say how value should be mapped to option.
jarekucinski commentedon Nov 2, 2023
The same issue.
based on the documentation, I would never have guessed that the 'label' in getOptionLabel is from 'values' and not from 'options'.
I expect that the list of options is there to get information about options from it.
Moreover, as mentioned above, when using a react-hook-form we have to work around it by keeping an eye on everything in many places at the same time, where if it worked in accordance with the above proposal, it would solve many problems.
Like if you use react-query for getting options, and react-hook-form for now I would need to reset form/field on every available options update.
gaurav21r commentedon Jun 2, 2024
Agreed with everyone here and specifically @alenadvainova 's point
Converting the string back into an array using
Array.find()might seem as a simple workaround, but for my case I have an Array of over 200,000 elements being efficiently searched locally by Orama in an Table of<Autocomplete>sAs you can empathise, any extra
Array.findis a performance nuisance!@ZeeshanTamboli @michaldudak As many others have mentioned,
isOptionEqualToValueworks in this case, so I think the issue should be resolved with a change in the type definitions only?ZeeshanTamboli commentedon Jun 4, 2024
@gaurav21r This issue is being tracked in mui/base-ui#45.
aress31 commentedon Jan 8, 2025
@michaldudak @ZeeshanTamboli still waiting on this, the getOptionLabel should have the selected option rather than the value to decouple the processed value from the displayed label. For instance, I do send the id only to my backend but display the name of the object. Right now this is a pain to get this working with autocomplete, by using the options as primary source for the autocomplete as opposed to the value that would solve the issue.
michaldudak commentedon Jan 8, 2025
I don't think there are plans to update the existing Autocomplete before switching the implementation to Base UI's Combobox (@aarongarciah, correct me if I'm wrong).
aarongarciah commentedon Jan 8, 2025
@michaldudak correct #44863 (comment)
[-][Autocomplete] `getOptionLabel` callback is getting the value instead of option object[/-][+][autocomplete] `getOptionLabel` callback is getting the value instead of option object[/+]aress31 commentedon Jun 28, 2025
ping
mj12albert commentedon Apr 21, 2026
#23708 (comment)