4

I have created a dropdown menu using Material UI select. It says "Search By". When we click it, it gives us a list. When I select one of the options, I want to store the option and change the "Search By" to the option selected.

export default function UserSearchPage(){ const [criteria, setCriteria] = useState(''); const [searchItem, setSearchItem] = useState(''); return ( <div> <div className='main-content'> <Select value = {criteria} onChange={ value => { setCriteria(value);} } displayEmpty > <MenuItem disabled value=""> <em>Search By</em> </MenuItem> <MenuItem value={1}>First Name</MenuItem> <MenuItem value={2}>Last Name</MenuItem> <MenuItem value={3}>Phone Number</MenuItem> <MenuItem value={4}>Email</MenuItem> </Select> </div> ) </div> ); } 

Currently, the onChange gives me this error on value:

Argument of type 'ChangeEvent<{ name?: string | undefined; value: unknown; }>' is not assignable to parameter of type 'SetStateAction<string>'. Type 'ChangeEvent<{ name?: string | undefined; value: unknown; }>' is not assignable to type '(prevState: string) => string'. 

and if I use this:

onChange={event => setCriteria(event.target.value)} 

I get:

Argument of type 'unknown' is not assignable to parameter of type 'SetStateAction<string>'. Type 'unknown' is not assignable to type '(prevState: string) => string'. 

2 Answers 2

7

You have to assert the unknown typed values before using them. If you're sure that the values from onChange events will always be strings, then you can do onChange={event => setCriteria(event.target.value as string)} and the compiler should no longer complain.

Sign up to request clarification or add additional context in comments.

4 Comments

This works but I am a bit confused. I am using this on my search bar on the same page and it works onChange={value => { setSearchItem(value);}}so how come the same pattern doesn't work for the select?
I'm assuming you mean your TextInput's onChange here. The type definitions for TextInput's onChange and Select's onChange are not the same. Material UI developers decided to make the value type unknown for some (I'm sure justified) reason, so you have to do the assertion on that.
Nope, I meant onChange() for Material UI's SearchBar but yeah the explanation makes sense
@giotskhada Thank you for your answer. Do you have a recommendation how one could achieve this when using union types (e.g. string | number)?
1

define a type to your event argument. So it would be

onChange={event:React.ChangeEvent<{ value: unknown }> => setCriteria(event.target.value)} 

4 Comments

I get this error on onChange: No overload matches this call. Overload 1 of 2, '(props: SelectProps, context?: any): ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<...>)> | Component<...> | null', gave the following error.
Cannot find name 'value'.
Maybe you could try here after changing .js files to .tsx codesandbox.io/s/…
if you have strict lint validation this will fail. first answer is the safe way to do that.