How can I control a RadioGroup from material-ui?
Asked Answered
F

2

6

I have a React (typescript) app where I want to show a radio group but cut into two columns like so: enter image description here

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.

Flowering answered 20/11, 2019 at 11:0 Comment(0)
F
7

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.

Flowering answered 20/11, 2019 at 13:17 Comment(0)
D
3

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);
Disepalous answered 20/11, 2019 at 12:1 Comment(1)
Thank you! I adapted your code to successfully reproduce my situation. I have found the problem and will write an answer for it. Thanks for your help!Flowering

© 2022 - 2024 — McMap. All rights reserved.