Đặt giá trị nút radio trong React

Nov 24 2020

Tôi đang tạo một ứng dụng phản ứng đơn giản với biểu mẫu có các nút radio.

Ở đây có sẵn một dữ liệu mặc định như,

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

Yêu cầu:

-> Cần lặp lại điều này defaultDatavà chỉ định ContactModechế độ tương ứng của chúng như đã chọn trong mỗi hàng.

Đoạn mã hoạt động:

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>

Sản lượng mong đợi:

Contact Mode  Email Text Both (Checked)

Contact Mode  Email Text(Checked) Both

Contact Mode  Email Text(Checked) Both

Lưu ý: Tôi không thể sửa đổi thuộc tính tên name="ContactMode".. Lý do là tôi cũng có nút lưu riêng cho mỗi hàng và khi nhấp vào nút lưu đó, hàng cụ thể sẽ được lưu .. Và mỗi hàng phải có name="ContactMode"..

Biên tập:

Vì câu hỏi của tôi không rõ ràng về những gì tôi đang cố gắng đạt được, tôi sẽ cung cấp toàn bộ mã ở đây.

-> Tôi có một biểu mẫu bước trong đó Bước 2 là phần việc làm và theo mặc định, tôi có các giá trị để đặt vào biểu mẫu,

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

-> Inside useEffecthook, tôi đặt giá trị biểu mẫu như,

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

Ở đây, các giá trị biểu mẫu với các hộp đầu vào được liên kết đúng cách nhưng giá trị nút radio không được chọn.

-> Có sẵn hai dữ liệu nhưng dữ liệu đầu tiên sẽ được mở rộng theo mặc định và trong khi dữ liệu thứ hai sẽ được mở khi nhấp vào Expandnút bên dưới dữ liệu đầu tiên.

-> Khi nhấp vào savenút, đối tượng cụ thể đó ( inputField) sẽ được ghi vào bảng điều khiển (chỉ thử nghiệm) cùng với dữ liệu đã sửa đổi ..

Ở đây ISSUE là nếu chúng tôi sửa đổi dữ liệu thì mọi thứ vẫn hoạt động tốt nhưng chỉ riêng thuộc tính đã kiểm tra vô tuyến không làm cho mục được kiểm tra .. (Chỉ báo đã kiểm tra không hoạt động) ..

Vui lòng chuyển sang bước 2 trong hộp mã cụ thể bên dưới để xem sự cố .. Để xem mục thứ hai, hãy nhấp vào nút mở rộng ..

Vui lòng giúp tôi đặt giá trị nút radio mặc định trong mỗi hàng.

Trả lời

1 DrewReese Nov 25 2020 at 14:15

Trong hộp cát của bạn, tôi có thể làm cho các nút radio hoạt động nhờ

  1. Cung cấp tính năng duy nhất namecho mỗi nhóm radio được ánh xạ
  2. Cập nhật trình xử lý thay đổi để xử lý duy nhất thuộc ContactModetính.

Cập nhật các nhóm radio để sử dụng chỉ mục được ánh xạ hiện tại nhằm làm cho chúng trở thành duy nhất trong số tất cả các nhóm được ánh xạ.

<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>

Trong handleInputChangetrường hợp thêm để xử lý ContactModeđặc biệt.

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

Tôi nghĩ rằng đó là do tất cả các đài phát thanh có cùng một thuộc tính tên, mỗi nhóm nên có tên khác nhau. ví dụ:

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

cho mọi tên do nhóm mới như thế này. nếu bạn trùng tên nó sẽ khiến mọi thứ rối tung lên, người khác nghĩ bạn là bạn ==thay vì===

item.ContactMode == 3

tốt hơn là sử dụng ===

vkvkvk Nov 24 2020 at 22:49

Câu trả lời của @ TalOrlanczyk là đúng. Bạn đang in tổng cộng 9 nút radio và tất cả đều có cùng giá trị trong thuộc tính name. Vì vậy, về mặt kỹ thuật, nó giống như việc có một nhóm radio có 9 nút radio, nghĩa là một nhóm radio chỉ có thể chấp nhận một giá trị. Tôi đã chạy mã của bạn và nó chỉ chọn "Văn bản" trên dòng thứ 3.

Nếu bạn đang cố gắng có 3 hàng riêng biệt (nhóm radio), bạn cần thử một cái gì đó như sau:

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

Hãy thử và chạy lại mã của bạn

NeetigyaChahar Nov 25 2020 at 13:16

Đây là một số vấn đề trong mã của bạn ...

  1. Mỗi khi thành phần trả về, .mapnó sẽ được gọi defaultData. Do đó không được ánh xạ tới trạng thái.

  2. Nếu bạn muốn có cùng một tên cho mỗi lần lặp, thì bạn cần phải sử dụng <form>cho mỗi lần lặp, nếu không tất cả các nút radio sẽ được nhóm lại với nhau, do đó chỉ nút radio cuối cùng hiển thị là đã đánh dấu.

  3. Tốt hơn là sử dụng ===thay vì==

Tôi đã sửa đổi mã của bạn và defaultDatađược sử dụng để khởi tạo trạng thái.

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>