在 React 中设置单选按钮值

IT技术 javascript html reactjs radio-button
2021-04-28 22:09:27

我正在制作一个带有单选按钮的简单react应用程序。

这里有一个可用的默认数据,例如,

const defaultData = [{ ContactMode: 3 }, { ContactMode: 2 }, { ContactMode: 2 }];

要求:

-> 需要迭代这个defaultDataContactMode在每一行中指定它们各自的模式。

工作片段:

const { useState } = React;

const App = () => {
  const [formValue, setFormValue] = useState({
    ContactMode: 1
  });

  const defaultData = [{ ContactMode: 3 }, { ContactMode: 2 }, { ContactMode: 2 }];

  const handleInputChange = (e, index) => {
    const { name, value } = event.target;
    setFormValue({
      ...formValue,
      [name]: value
    });
  };

  const submitData = () => {
    console.log(formValue);
  };

  return (
    <div>
      <form>
        {defaultData.map((item, index) => {
          return (<React.Fragment>
            <label> Contact Mode </label>
            <input
              type="radio"
              name="ContactMode"
              checked={item.ContactMode == 1}
              value={1}
              onChange={(event) => handleInputChange(index, event)}
            />{" "}
            Email
            <input
              type="radio"
              name="ContactMode"
              checked={item.ContactMode == 2}
              value={2}
              onChange={(event) => handleInputChange(index, event)}
            />{" "}
            Text
            <input
              type="radio"
              name="ContactMode"
              checked={item.ContactMode == 3}
              value={3}
              onChange={(event) => handleInputChange(index, event)}
            />{" "}
            Both
            <br />
            <br />
            <button type="button">
               Save
             </button>
            <br />
            <br />
            <br />
          </React.Fragment>);
        })}
      </form>
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.11.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>

预期输出:

Contact Mode  Email Text Both (Checked)

Contact Mode  Email Text(Checked) Both

Contact Mode  Email Text(Checked) Both

注意:我无法修改 name 属性name="ContactMode"..原因是我每行都有单独的保存按钮,点击该保存按钮时,特定行将被保存..每行应该有name="ContactMode"..

编辑:

由于我的问题不清楚我要实现的目标,因此我将在此处提供整个代码。

->我有一个 stepper 表单,其中第 2 步是就业部分,默认情况下我有要设置到表单中的值,

const dynamicData = [
  {
    EmploymentID: 1,
    companyName: 'Company One',
    designation: 'Designation One',
    ContactMode: 3,
  },
  {
    EmploymentID: 2,
    companyName: 'Company two',
    designation: 'Designation One',
    ContactMode: 2,
  },
];

->useEffect钩子里面我设置了表单值,比如,

  React.useEffect(() => {
    setExpanded(0);
    setValue((prev) => {
      const companyDetails = [...dynamicData];
      return { ...prev, companyDetails };
    });
  }, []);

此处带有输入框的表单值已正确绑定,但未选中单选按钮值。

->有两个数据可用,但默认情况下第一个将展开,而第二个将通过单击Expand第一个下方的按钮打开

->单击save按钮后,该特定对象 ( inputField) 将与修改后的数据一起被控制台记录(仅用于测试)。

这里的问题是,如果我们修改数据,那么一切正常,但单单无线电检查属性不会使项目检查..(检查指示不起作用)。

请转到下面给出的代码和框中的第 2 步以查看问题。要查看第二项,请单击展开按钮。

编辑下一个动态测试问题(分叉)

请帮助我在每一行中设置默认单选按钮值。

4个回答

在你的沙箱中,我能够让单选按钮工作

  1. name每个映射的无线电组提供唯一
  2. 更新更改处理程序以唯一处理该ContactMode属性。

更新无线电组以使用当前映射的索引,以使它们在所有映射组中唯一。

<div className="form-group col-sm-4">
  <label className="inline-flex items-center mr-6">
    <input
      type="radio"
      className="form-radio border-black"
      name={`ContactMode-${index}`} // <-- append index to name
      value={1}
      checked={inputField.ContactMode === 1} // <-- use strict "==="
      onChange={(event) => handleInputChange(index, event)}
    />
    <span className="ml-2">Email</span>
  </label>
</div>
<div className="form-group col-sm-4">
  <label className="inline-flex items-center mr-6">
    <input
      type="radio"
      className="form-radio border-black"
      name={`ContactMode-${index}`}
      value={2}
      checked={inputField.ContactMode === 2}
      onChange={(event) => handleInputChange(index, event)}
    />
    <span className="ml-2">Text</span>
  </label>
</div>
<div className="form-group col-sm-4">
  <label className="inline-flex items-center mr-6">
    <input
      type="radio"
      className="form-radio border-black"
      name={`ContactMode-${index}`}
      value={3}
      checked={inputField.ContactMode === 3}
      onChange={(event) => handleInputChange(index, event)}
    />
    <span className="ml-2">Both</span>
  </label>
</div>

handleInputChange加一个caseContactMode专门处理

const handleInputChange = (index, event) => {
  const { name, value } = event.target;
  if (name === 'designation' && !isLettersOnly(value)) {
    return;
  }

  if (name.startsWith('ContactMode')) { // <-- check name prefix
    setValue((prev) => ({
      ...prev,
      companyDetails: prev.companyDetails.map((detail, i) =>
        i === index
          ? {
              ...detail,
              ContactMode: Number(value), // <-- store back under correct key, as number for string equality check
            }
          : detail,
      ),
    }));
    return; // <-- return early so other state update is skipped!
  }

  setValue((prev) => {
    const companyDetails = prev.companyDetails.map((v, i) => {
      if (i !== index) {
        return v;
      }

      return { ...v, [name]: value };
    });

    return { ...prev, companyDetails };
  });
};

编辑 set-radio-button-value-in-react

我认为这是由于所有收音机都有相同的名称属性,每个组都应该有不同的名称。例如:

name = " ex1"
name = "ex2"
name = "ex3"

对于每个这样的新组应有的名称。如果你用同样的名字,它会让一切都变得一团糟,另一个认为你是你==而不是===

item.ContactMode == 3

最好使用 ===

@TalOrlanczyk 的回答是正确的。您总共打印了 9 个单选按钮,并且在 name 属性中都具有相同的值。所以从技术上讲,它就像有一个带有 9 个单选按钮的单选组,这意味着一个单选组只能接受一个值。我运行了你的代码,它只在第三行选择了“文本”。

如果您尝试有 3 个单独的行(无线电组),您需要尝试这样的事情:

<input
    type="radio"
    name={"ContactMode"+index}
    checked={item.ContactMode == 1}
    value={1}
    onChange={(event) => handleInputChange(index, event)}
/>{" "}
Email
<input
    type="radio"
    name={"ContactMode"+index}
    checked={item.ContactMode == 2}
    value={2}
    onChange={(event) => handleInputChange(index, event)}
/>{" "}
Text
<input
    type="radio"
    name={"ContactMode"+index}
    checked={item.ContactMode == 3}
    value={3}
    onChange={(event) => handleInputChange(index, event)}
/>{" "}

尝试并重新运行您的代码

这是您的代码中的一些问题...

  1. 每次组件返回时,.map都会调用defaultData因此没有映射到状态。

  2. 如果您希望<form>每次迭代都使用相同的名称,那么您需要在每次迭代中使用,否则所有单选按钮将组合在一起,因此只有最后一个单选按钮显示为标记。

  3. 最好使用===而不是==

我已经修改了您的代码并defaultData用于初始化状态。

const { useState } = React;


  const defaultData = [{ ContactMode: 3 }, { ContactMode: 2 }, { ContactMode: 2 }];

const App = () => {

  const [formValue, setFormValue] = useState([...defaultData]);

  const handleInputChange = (index, e) => {
    const { name, value } = e.target;

    const newFormValue = [...formValue];
    newFormValue.splice(index,1,{[name]: value});
    
    setFormValue(newFormValue);
  };

  const submitData = () => {
    console.log(formValue);
  };

  return (
    <div>
        {formValue.map((item, index) => {
          return (<form>
            <label> Contact Mode </label>
            <input
              type="radio"
              name="ContactMode"
              checked={Number(item.ContactMode) === 1}
              value={1}
              onChange={(event) => handleInputChange(index, event)}
            />{" "}
            Email
            <input
              type="radio"
              name="ContactMode"
              checked={Number(item.ContactMode) === 2}
              value={2}
              onChange={(event) => handleInputChange(index, event)}
            />{" "}
            Text
            <input
              type="radio"
              name="ContactMode"
              checked={Number(item.ContactMode) === 3}
              value={3}
              onChange={(event) => handleInputChange(index, event)}
            />{" "}
            Both
            <br />
            <br />
          </form>);
        })}
        <button type="button" onClick={submitData}>
          {" "}
          Submit{" "}
        </button>
    </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.11.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>