Reactでラジオボタンの値を設定する

Nov 24 2020

ラジオボタンのあるフォームでシンプルなReactアプリを作っています。

ここに、次のような利用可能なデフォルトデータがあります。

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

要件:

->これを繰り返し、各行でチェックされdefaultDataているようにそれぞれのContactModeモードを割り当てる必要があります。

ワーキングスニペット:

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="ContactMode"。理由は、各行に個別の保存ボタンがあり、その保存ボタンをクリックすると、特定の行が保存されるためです。各行にはname="ContactMode"..が必要です。

編集:

私の質問は私が何を達成しようとしているのか明確ではないので、ここでコード全体を示します。

->ステップ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 };
    });
  }, []);

ここでは、入力ボックスを含むフォーム値が適切にバインドされていますが、ラジオボタンの値はチェックされていません。

->利用可能なデータは2つありますが、最初のデータはデフォルトで展開され、2番目のデータは最初のデータのExpand下にあるボタンをクリックすると開きます。

- >のクリックでsaveボタン、その特定のオブジェクトは、( inputField)コンソールは、修正されたデータと一緒に(テストのみ)記録されます..

ここでの問題は、データを変更すると正常に機能しますが、無線チェック属性だけではアイテムがチェックされないことです。(チェックされた表示は機能しません)。

以下のコードサンドボックスのステップ2に進んで、問題を確認してください。2番目の項目を確認するには、展開ボタンをクリックします。

各行にデフォルトのラジオボタン値を設定するのを手伝ってください。

回答

1 DrewReese Nov 25 2020 at 14:15

あなたのサンドボックスで、私はラジオボタンを機能させることができました

  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処理する場合の追加ContactMode特別に。

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 };
  });
};

1 TalOrlanczyk Nov 24 2020 at 22:10

すべてのラジオが同じ名前属性を持っているため、グループごとに異なる名前を付ける必要があると思います。例えば:

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

このような新しいグループの名前ごとに。あなたが同じ名前をすると、それはすべてを台無しにして別の人にあなたの==代わりにあなたを思わせる===

item.ContactMode == 3

使用する方が良いです ===

vkvkvk Nov 24 2020 at 22:49

@TalOrlanczykの答えは正しいです。合計9つのラジオボタンを印刷しており、名前属性の値はすべて同じです。つまり、技術的には、9つのラジオボタンを備えたラジオグループを持つようなものです。つまり、ラジオグループは1つの値しか受け入れることができません。コードを実行しましたが、3行目の「テキスト」のみが選択されました。

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)}
/>{" "}

それを試して、コードを再実行してください

NeetigyaChahar Nov 25 2020 at 13:16

コードにいくつかの問題があります...

  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>