Search code examples
reactjstoggleradio-group

Controlled Radio Group Button updates only 1st group when value of other radio group gets changed - in React


Here I'm trying to render a table of members having 3 radio buttons for each member (Attending, Tentative, Not Attending) along with it's name.

I've saved each memberRow's state in option state var & was expecting when I update option of 2nd member, it updates the 1st one.

Fiddle Link


Solution

  • You have an issue with the id in your input tag. You must use a unique id in each input tag and each row. In label you use htmlFor as the id is not unique in rows it will always point out to the first id match. So your case it will be the first row. So change is always reflected in the first row only.

    import { useState } from "react";
    
    const RowAction = ({ member, index }) => {
      const [option, setOption] = useState(member.response);
    
      const onRadioChange = (e) => {
        let selected;
        switch (e.target.value) {
          case "1":
            selected = 1;
            break;
          case "-1":
            selected = -1;
            break;
          case "0":
            selected = 0;
            break;
          default:
            selected = null;
        }
        setOption(selected);
      };
      return (
        <tr key={member.name}>
          <td>{member.name}</td>
          <td>
            <div className="switch-field">
              <input
                type="radio"
                id={`attending${index}`}
                value={1}
                checked={option === 1}
                onChange={onRadioChange}
              />
              <label
                htmlFor={`attending${index}`}
                className={option === 1 ? "attending" : ""}
              >
                ATTENDING
              </label>
              <input
                type="radio"
                id={`tentative${index}`}
                value={-1}
                checked={option === -1}
                onChange={onRadioChange}
              />
              <label
                htmlFor={`tentative${index}`}
                className={option === -1 ? "tentative" : ""}
              >
                TENTATIVE
              </label>
              <input
                type="radio"
                id={`notAttending${index}`}
                value={0}
                checked={option === 0}
                onChange={onRadioChange}
              />
              <label
                htmlFor={`notAttending${index}`}
                className={option === 0 ? "notattending" : ""}
              >
                NOT ATTENDING
              </label>
            </div>
          </td>
        </tr>
      );
    };
    
    export default RowAction;
    

    Working sample https://codesandbox.io/s/dreamy-darkness-posvv7