Reputation: 4839
I need to generate the groupings of my Select component dynamically and would like to use the component in a controlled way. (As opposed to uncontrolled.)
This code snippet works fine without the <ListSubheader ...>
component, however I need it and the Material UI Docs example for group select shows using the <ListSubheader ...>
component in this way.
<Select fullWidth value={selectedPlan} onChange={handleChange}>
{products?.map(p => (
<>
<ListSubheader>{p.name}</ListSubheader>
{p.plans.map(pl => (
<MenuItem key={pl.id} value={pl}>
{pl.id} {pl.name} {pl.type} {pl.price}
</MenuItem>
))}
</>
))}
</Select>
However it seems impossible to generate this dynamically if we are getting the error message
The Menu component doesn't accept a Fragment as a child. Consider providing an array instead.
According to the Material UI documentation,
⚠️The MenuItem elements must be direct descendants when native is false.
How can I programatically generate my groupings in my component.
I have created a code sandbox where this problem is reproducible
Upvotes: 10
Views: 10881
Reputation: 21
This code works fine:
<Select fullWidth value={selectedPlan} onChange={handleChange}>
{products?.reduce((acc, p) => {
acc.push(
<ListSubheader key={`subheader-${p.name}`}>{p.name}</ListSubheader>
);
acc.push(
...p.plans.map(pl => (
<MenuItem key={pl.id} value={pl}>
{pl.id} {pl.name} {pl.type} {pl.price}
</MenuItem>
))
);
return acc;
}, [])}
</Select>
Upvotes: 2
Reputation: 621
Try consider using Autocomplete which has more straightforward support for this kind of query
<Autocomplete
multiple
id="checkboxes-tags-demo"
options={niche_data}
groupBy={(option) => option.niche}
onChange={(e, v) => {
onChange(v);
}}
getOptionLabel={(option) => option.sub_niche}
renderOption={(props, data) => (
<Typography key={data.id} {...props} variant="body1">
{data.sub_niche}
</Typography>
)}
style={{ width: 500 }}
renderInput={(params) => (
<TextField
{...params}
variant="outlined"
label="niches/Companies"
placeholder="Relationships/Companies"
/>
)}
/>;
Where data is
const niche_data = [
{id:1,sub_niche:"CBD Oil",niche:"CBD"},
{id:2,sub_niche:"CBD Pets",niche:"CBD"},
{id:3,sub_niche:"CBD Skincare",niche:"CBD"},
{id:4,sub_niche:"CBD Edibles",niche:"CBD"},
{id:5,sub_niche:"CBD Vapes",niche:"CBD"},
{id:6,sub_niche:"CBD Beauty",niche:"CBD"},
{id:7,sub_niche:"Weightloss",niche:"Food supplements"},
{id:8,sub_niche:"Sports nutrition",niche:"Food supplements"},
{id:9,sub_niche:"Nootropic",niche:"Food supplements"},
{id:11,sub_niche:"Vitamins",niche:"Food supplements"},
{id:12,sub_niche:"Face oil",niche:"Skincare"},
{id:13,sub_niche:"Facecream",niche:"Skincare"},
{id:14,sub_niche:"Cleanser",niche:"Skincare"},
{id:15,sub_niche:"Lip balm",niche:"Skincare"},
{id:16,sub_niche:"Serum & Tones",niche:"Skincare"},
]
Upvotes: 0
Reputation: 11
I had the same problem with the selector and it helped me to replicate some of this code https://codesandbox.io/s/mui-select-grouping-problem-i9jtj?file=/src/App.js:1662-1704 if the component expects you to take a single array and not a group try a reduce() like this https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
Upvotes: 1
Reputation: 1330
Here is the edited sandbox.
Yes, the issue was that you had it wrapped in a fragment. If you wrap it in a <div>
it works but returns undefined
for event.target.value
since <MenuItem/>
is not a direct child of <Select/>
.
P.S. I extracted it to a function just make it more clear. It has nothing to do with the fix.
Upvotes: 18