Reputation: 1153
I have a React (typescript) app where I want to show a radio group but cut into two columns like so:
To do so, I use two RadioGroup from @material-ui/core
that I wish to completely control so the user cannot select an option in each group. My problem is that the RadioGroups don't care about the value
I give them, they seem to be working in uncontrolled mode. I can even see that the value is OK in their props, in the React DevTools.
Here is how I did it:
<div>Organizational attributes</div>
<div>
<RadioGroup
value={selectedPivotAttribute && selectedPivotAttribute.id.toString()}
onChange={selectPivotAttribute}
>
{props.attributes.filter(attribute => attribute.isHierarchical).map(attribute => (
<FormControlLabel
label={attribute.name}
key={attribute.id}
value={attribute.id.toString()}
control={<Radio/>}
/>
))}
</RadioGroup>
</div>
<div>Secondary attributes</div>
<div>
<RadioGroup
value={selectedPivotAttribute && selectedPivotAttribute.id.toString()}
onChange={selectPivotAttribute}
>
{props.attributes.filter(attribute => !attribute.isHierarchical).map(attribute => (
<FormControlLabel
label={attribute.name}
key={attribute.id}
value={attribute.id.toString()}
control={<Radio/>}
/>
))}
</RadioGroup>
</div>
The two RadioGroups are correctly rendered and functional, they also trigger the onChange
handler, but they don't care about the value I give them, they just live their own life and thus they are not mutually exclusive.
I am trying to reproduce in a codesandbox but I can't even get one RadioGroup to work at all in there. Here it is anyway: https://codesandbox.io/s/gallant-cloud-yixdd. I can't think of anything simpler than that while remaining relevant to the case.
Upvotes: 6
Views: 15071
Reputation: 1153
Thanks to Alessio's answer I managed to reproduce my situation in a code sandbox available here: https://codesandbox.io/s/vigorous-napier-huo9b.
In the sandbox, line 47, I set the default value for the state to be an empty string. If you remove that to set it to undefined
, it will not work.
So the real problem is that when you don't provide a value
to RadioGroup
(or if you provide undefined
), the component will be uncontrolled. Simple as that. To avoid that, I just needed to provide an empty string rather than undefined
when no selection is intended.
Upvotes: 7
Reputation: 584
https://codesandbox.io/s/gallant-cloud-hyq90
That's how i manage to make it works
import React from "react";
import ReactDOM from "react-dom";
import {
RadioGroup,
FormControlLabel,
Radio,
FormLabel
} from "@material-ui/core";
import "./styles.css";
const data = [
{
id: "1",
value: "Hello"
},
{
id: "2",
value: "How"
},
{
id: "3",
value: "are"
},
{
id: "4",
value: "you"
}
];
const data2 = [
{
id: "1",
value: "fine"
},
{ id: "2", value: "ty" }
];
function App() {
const [selection, setSelection] = React.useState({
value: "1",
value2: "1"
});
const updateSelection = (event, value) => {
event.persist();
const name = event.target.name;
setSelection({ ...selection, [name]: value });
};
return (
<div className="App">
<FormLabel component="legend">Howdy</FormLabel>
Value1: {selection.value}, Value2: {selection.value2}
<RadioGroup
name="value"
value={selection.value}
onChange={updateSelection}
>
{data.map(datum => (
<FormControlLabel
label={datum.value}
key={datum.id}
value={datum.id}
control={<Radio color="primary" />}
/>
))}
</RadioGroup>
<RadioGroup
name="value2"
value={selection.value2}
onChange={updateSelection}
>
{data2.map(datum => (
<FormControlLabel
label={datum.value}
key={datum.id}
value={datum.id}
control={<Radio color="primary" />}
/>
))}
</RadioGroup>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Upvotes: 3