Let's start by consider this little snippet:
import "./styles.css";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import ListItemSecondaryAction from "@material-ui/core/ListItemSecondaryAction";
import ListItemText from "@material-ui/core/ListItemText";
import Checkbox from "@material-ui/core/Checkbox";
import Select from "@material-ui/core/Select";
import React, { Component } from "react";
class WidgetList extends Component {
constructor(props) {
super(props);
this.state = {};
}
onChangeTag = (event, item) => {
item.tag = event.target.value;
console.log("changing tag", event.target, item.name);
};
render() {
const { allItems } = this.props;
const { selectedItems } = this.props;
return (
<List>
{allItems.map((item) => {
return (
<ListItem
key={item.name}
role={undefined}
dense
button
disableRipple
>
<ListItemIcon>
<Checkbox
edge="start"
checked={selectedItems.has(item)}
tabIndex={-1}
disableRipple
/>
</ListItemIcon>
<ListItemText primary={`${item.name}`} />
<ListItemSecondaryAction>
<Select
native
value={item.tag}
onChange={(e) => this.onChangeTag(e, item)}
>
<option value={0}>foo</option>
<option value={1}>bar</option>
<option value={2}>baz</option>
</Select>
</ListItemSecondaryAction>
</ListItem>
);
})}
</List>
);
}
}
let allItems = [
{ name: "1", tag: 0 },
{ name: "2", tag: 1 },
{ name: "3", tag: 2 }
];
let selectedItems = new Set([allItems[0], allItems[1]]);
export default function App() {
return (
<div className="App">
<WidgetList allItems={allItems} selectedItems={selectedItems} />
</div>
);
}
I'd like to understand what's the way to change the value of the select widgets when clicking a different one. Right now no matter which one you select the widget won't change.
To see what I mean you can play with it on this sandbox, no matter if you select foo
, bar
, baz
values on the select widget the widget itself won't update.
To set the default value in React Material-UI select box, we can set the initial value of the state that we use as the Select 's value prop's value. The initial value must match one of the value prop of values of MenuItem . to define the value state with useState . We set value 's initial value to "50k-100k" .
To change the dropdown icon in React Material UI select field, we can set the IconComponent prop to a function that returns the icon component we want to render. We set the Select 's IconComponent prop to a function that returns the Person icon component. And we add some MenuItem components to add some choices.
The MUI Select component is an input/dropdown combo that comes with dozens of configurable props. In this tutorial I will customize the dropdown position, the default and placeholder values, add multiselect, and add labels and helper text, and more. MUI Select with Dropdown Offset and Placeholder Value.
In this short article, we would like to show how to use in React project, Material-UI Select component with array of objects as options. By default, the select component doesn't use an options array, so it is necessary to add items inside using JSX notation. Presented solution uses controlled component mode ( value and onChange ).
To set the default value in React Material-UI select box, we can set the initial value of the state that we use as the Select ‘s value prop’s value. The initial value must match one of the value prop of values of MenuItem. to define the value state with useState. We set value ‘s initial value to "50k-100k".
If you take a look at the Select Api of Material UI here, you could do it easily. As explained above, you need to pass the default value in your state variable: const [age, set Age] = React.useState (10); // < --------------(Like this) .
With an uncontrolled component, you often want React to specify the initial value, but leave subsequent updates uncontrolled. To handle this case, you can specify a defaultValue attribute instead of value. You need to update allItems value on onChange for working of onChange select i.e
You need to change your approach to store selected items state so that it can handle that efficiently.
The main mistake was in this line:
item.tag = event.target.value;
You cannot do that because the item is immutable.
I have updated the code from your sandbox to make the select work properly.
import "./styles.css";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import ListItemSecondaryAction from "@material-ui/core/ListItemSecondaryAction";
import ListItemText from "@material-ui/core/ListItemText";
import Checkbox from "@material-ui/core/Checkbox";
import Select from "@material-ui/core/Select";
import React, { Component } from "react";
class WidgetList extends Component {
constructor(props) {
super(props);
this.state = {
allItems: [],
selectedItems: {}
};
}
onChangeTag = (event, item) => {
this.setState({
selectedItems: {
...this.state.selectedItems,
[selectedItems[item.tag.toString()]]: event.target.value
}
});
};
render() {
const { allItems } = this.props;
const { selectedItems } = this.props;
return (
<List>
{allItems.map((item) => {
return (
<ListItem
key={item.name}
role={undefined}
dense
button
disableRipple
>
<ListItemIcon>
<Checkbox
edge="start"
checked={selectedItems.has(item)}
tabIndex={-1}
disableRipple
/>
</ListItemIcon>
<ListItemText primary={`${item.name}`} />
<ListItemSecondaryAction>
<Select
native
value={selectedItems[item.tag.toString()]}
onChange={(e) => this.onChangeTag(e, item)}
>
<option value={0}>foo</option>
<option value={1}>bar</option>
<option value={2}>baz</option>
</Select>
</ListItemSecondaryAction>
</ListItem>
);
})}
</List>
);
}
}
let allItems = [
{ name: "1", tag: 0 },
{ name: "2", tag: 1 },
{ name: "3", tag: 2 }
];
let selectedItems = new Set([allItems[0], allItems[1]]);
export default function App() {
return (
<div className="App">
<WidgetList allItems={allItems} selectedItems={selectedItems} />
</div>
);
}
You can achieve the same result without using state
(as what suggested by most answers) by implementing an uncontrolled component
. This way data will be handled by the DOM and not by React.
Just change the value
prop on your Select
component to defaultValue
.
<Select
native
defaultValue={item.tag}
onChange={(e) => this.onChangeTag(e, item)}
>
<option value={0}>foo</option>
<option value={1}>bar</option>
<option value={2}>baz</option>
</Select>
From the docs
With an uncontrolled component, you often want React to specify the initial value, but leave subsequent updates uncontrolled. To handle this case, you can specify a
defaultValue
attribute instead ofvalue
.
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