Material-ui: Support objects with <Select>

Created on 29 Mar 2018  路  17Comments  路  Source: mui-org/material-ui

  • [x] I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior


Not showing warnings when passing an object as value to the Select component.

Current Behavior


It works but it is showing these warnings:

  • Warning: Failed prop type: Invalid prop 'value' supplied to 'Select'.
  • Warning: Failed prop type: Invalid prop 'value' supplied to 'Input'.
  • Warning: Failed prop type: Invalid prop 'value' supplied to 'SelectInput'.

Steps to Reproduce (for bugs)


Thats my component in which I use the Select component. As you can see this.props.selectedWorkingStep is an object which causes those warnings.

class WorkingStepSelect extends React.Component {
    render() {
        return <FormControl error={this.props.error} className={this.props.classes.formControl}>
            <InputLabel htmlFor="workingStepSelect">{germanMessages.resources.controls.workingStepSelect.label}</InputLabel>
            <Select
                value={this.props.selectedWorkingStep}
                onChange={this.props.onChangeWorkingStep}
                input={<Input name="workingStep" id="workingStepSelect" />}
            >
                {this.props.workingSteps.map((workingStep) => {
                    return <MenuItem key={workingStep.id} value={workingStep}>{workingStep.name}</MenuItem>
                })}
            </Select>
            <FormHelperText className="error-message" error={this.props.error}>{germanMessages.resources.controls.workingStepSelect.errorMessages[this.props.error]}</FormHelperText>
        </FormControl>
    }
}

PropTypes:

WorkingStepSelect.propTypes = {
    selectedWorkingStep: PropTypes.any,
    workingSteps: PropTypes.arrayOf(PropTypes.object),
    onChangeWorkingStep: PropTypes.func,
    error: PropTypes.any,
    classes: PropTypes.object
};

CodeSandbox example

https://codesandbox.io/s/8x8r5plx32?module=%2Fsrc%2Fpages%2Findex.js

Context


Its not that critical because it is working for me(maybe there are errors which I don't encountered yet). Maybe #10834 has the same problem but I don't know it is the same reason for the warning because my warnings show up not depending on if I select an item of the Select.

Your Environment

| Tech | Version |
|--------------|---------|
| Material-UI | [email protected] |
| React | [email protected] |
| browser | Chrome Version 65 |
| etc | |

Select

Most helpful comment

I think that the best step going forward is to write a custom prop-type validator. The warning message isn't actionable right now:
https://github.com/mui-org/material-ui/blob/7f73f967c1f8c405eb14304de0bbd1aeae5b4d71/src/TextField/TextField.js#L261-L265

All 17 comments

@npeham Do you have a full reproduction example? It's hard to tell what's wrong without. You could be using CodeSandbox or StackBlitz.

Did you know if you have installed the material types? npm uninstall @types/material-ui work for me!

@oliviertassinari Sure: https://codesandbox.io/s/8x8r5plx32?module=%2Fsrc%2Fpages%2Findex.js

@astridcst In my codesandbox example I didn't add 'material types' and it is still showing me these warnings, so I don't think this is the problem or I just didn't get it what you mean.

@npeham Thanks a lot for the reproduction example! The value proptype isn't any.
It has to be a string or a number (or an array of this). You are providing an object to the component:

  {
    id: 1,
    name: "StepOne"
  }

While it's "working", it comes with two drawbacks:

  • You can't switch on and off the native property base on your environment. For instance, native={true} works great on mobile.
  • The value can't be serialized and sent down to the server with a raw POST/GET request:
    value="[object Object]"
    capture d ecran 2018-03-29 a 22 41 40
    It's important when you are using React and Material-UI as a server-side templating engine without client-side rendering and in different other niche use cases. I also "believe" it helps with accessibility.

Here is an updated version without the warning https://codesandbox.io/s/1yvymk2r67.

Now, I think that we should something about this confusing warning message. I have seen it too personally, wtf:
Warning: Failed prop type: Invalid prop 'value' supplied to 'Select'.

I have some issue, I think problem is when pass a array of object to value

This data will show warning:

[
    {id: 1, value='One'},
    {id: 2, value='Two'}
]

I think that the best step going forward is to write a custom prop-type validator. The warning message isn't actionable right now:
https://github.com/mui-org/material-ui/blob/7f73f967c1f8c405eb14304de0bbd1aeae5b4d71/src/TextField/TextField.js#L261-L265

@oliviertassinari About updated version, its works with single selects, but still have problem with multiple selects in renderValue*

Can't use this approach:

renderValue: selected =>
  {selected.map(value =>
    <Chip key={value.id} label={value.name} />
  )}

@luizrrodrigues

+values = {鈥

renderValue: selected =>
  {selected.map(value =>
-    <Chip key={value.id} label={value.name} />
+    <Chip key={values[value].id} label={values[value].name} />
  )}

@oliviertassinari

In this case can't pass .id to MenuItem, need pass index, then when pass state to POST need use map to get all IDs:

items = [
    {id: 32, name: 'John'},
    {id: 54, name: 'Mark'}
]
items.map((item, index) =>
    <MenuItem key={item.id} value={index}>
        <Checkbox checked={this.state.selectedItems.indexOf(index) > -1} />
        <ListItemText primary={item.name} />
    </MenuItem>
)

Data to POST:

itemsData: this.state.selectedItems.map(index =>
    return items[index].id
)

Now, I think that we should something about this confusing warning message. I have seen it too personally, wtf:
Warning: Failed prop type: Invalid prop 'value' supplied to 'Select'.

After some digging, I have realized that it's a broader issue with the prop-types package. The value property isn't the only property suffering from this limitation. It's not something worse fixing here. It would be much better to fix https://github.com/facebook/prop-types/issues/9.

@oliviertassinari Using the id as value for both MenuItem and Select works well. I understand now. Thank you very much!

@oliviertassinari Thanks, I'll follow.

@oliviertassinari Sorry for commenting on closed issue, but I think 'boolean' should be defined as a valid type for 'value'. I have a Select with true / false values and I got invalid prop type warning.

@ali-jalaal I haven't looked into the boolean. Interesting concern. As long as it's working for both the native and non-native select component, I think that we should be officiality supporting it :).

@npeham Thanks a lot for the reproduction example! The value proptype isn't any.
It has to be a _string_ or a _number_ (or an _array_ of this). You are providing an _object_ to the component:

  {
    id: 1,
    name: "StepOne"
  }

While it's "working", it comes with two drawbacks:

  • You can't switch on and off the native property base on your environment. For instance, native={true} works great on mobile.
  • The value can't be serialized and sent down to the server with a raw POST/GET request:
    value="[object Object]"
    capture d ecran 2018-03-29 a 22 41 40
    It's important when you are using React and Material-UI as a server-side templating engine without client-side rendering and in different other _niche use cases_. I also "believe" it helps with accessibility.

Here is an updated version without the warning https://codesandbox.io/s/1yvymk2r67.

Now, I think that we should something about this confusing warning message. I have seen it too personally, wtf:
Warning: Failed prop type: Invalid prop 'value' supplied to 'Select'.

@oliviertassinari

I am seeing this issue in the latest version.

And, regarding your reply about using only string or number as value, the API for Select doesn't state this:
https://material-ui.com/api/select/

value | union:聽string, number, bool, object, arrayOf | 聽 | The input value. This property is required when the聽nativeproperty is聽false聽(default).
-- | -- | -- | --

If the list of MenuItem elements contain an object as their value, shouldn't the Select element also accept object as value?

@don-p Do you have a minimal reproducible example? I've upgraded the reproduction above to use the latest version and it works fine. https://codesandbox.io/s/kon52opp4r

And, regarding your reply about using only string or number as value, the API for Select doesn't state this:

If you care about the actual values in the input you should always manually cast them to strings. The DOM doesn't allow for non-string values on input.

The type is wider in the propTypes because most of the feedback we got didn't care about the actual input value. The value that was passed to other parts of their software seemed to be constructed manually.

This is in line with how react-dom treats the input value. Technically it should warn about non-string values but seem to recognize that most users don't rely on the value.

For typescript users the current behavior is confusing though since <input /> only accepts number | string | string[]. But even here string[] doesn't make much sense because that value is also implicitly cast to string.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

FranBran picture FranBran  路  3Comments

revskill10 picture revskill10  路  3Comments

rbozan picture rbozan  路  3Comments

chris-hinds picture chris-hinds  路  3Comments

TimoRuetten picture TimoRuetten  路  3Comments