จะใช้ปุ่มตัวเลือกใน ReactJS ได้อย่างไร?


203

ฉันใหม่สำหรับ ReactJS ขออภัยหากปิดใช้งาน ฉันมีส่วนประกอบที่สร้างแถวของตารางหลายแถวตามข้อมูลที่ได้รับ

แต่ละเซลล์ภายในคอลัมน์จะมีช่องทำเครื่องหมายวิทยุ ดังนั้นผู้ใช้สามารถเลือกหนึ่งsite_nameและหนึ่งaddressจากแถวที่มีอยู่ การเลือกจะแสดงในส่วนท้าย และนั่นคือสิ่งที่ฉันติดอยู่

var SearchResult = React.createClass({
   render: function(){
       var resultRows = this.props.data.map(function(result){
           return (
               <tbody>
                    <tr>
                        <td><input type="radio" name="site_name" value={result.SITE_NAME}>{result.SITE_NAME}</input></td>
                        <td><input type="radio" name="address" value={result.ADDRESS}>{result.ADDRESS}</input></td>
                    </tr>
               </tbody>
           );
       });
       return (
           <table className="table">
               <thead>
                   <tr>
                       <th>Name</th>
                       <th>Address</th>
                   </tr>
               </thead>
                {resultRows}
               <tfoot>
                   <tr>
                       <td>chosen site name ???? </td>
                       <td>chosen address ????? </td>
                   </tr>
               </tfoot>
           </table>
       );
   }
});

ใน jQuery ฉันสามารถทำสิ่งที่ต้องการ$("input[name=site_name]:checked").val()เลือกประเภทของช่องทำเครื่องหมายวิทยุหนึ่งช่องและใส่ลงในเซลล์ส่วนท้ายแรก

แต่แน่นอนต้องมีวิธี Reactjs ซึ่งฉันหายไปทั้งหมด? ขอบคุณมาก


3
inputองค์ประกอบไม่มีเนื้อหา ดังนั้นจึง<input>content</input>ไม่มีเหตุผลและไม่ถูกต้อง <label><input />content</label>คุณอาจต้องการ
Oriol

1
ปุ่มตัวเลือกไม่จำเป็นต้องมีชื่อเหมือนกันซึ่งมีค่าต่างกันในการทำงานหรือไม่
pgee70

คำตอบ:


209

การเปลี่ยนแปลงใด ๆ ในการเรนเดอร์ควรเปลี่ยนผ่านทางstateหรือprops( ทำปฏิกิริยา doc )

ดังนั้นที่นี่ฉันลงทะเบียนเหตุการณ์ของอินพุตและจากนั้นเปลี่ยนstateซึ่งจะทริกเกอร์การเรนเดอร์เพื่อแสดงบนส่วนท้าย

var SearchResult = React.createClass({
  getInitialState: function () {
    return {
      site: '',
      address: ''
    };
  },
  onSiteChanged: function (e) {
    this.setState({
      site: e.currentTarget.value
      });
  },

  onAddressChanged: function (e) {
    this.setState({
      address: e.currentTarget.value
      });
  },

  render: function(){
       var resultRows = this.props.data.map(function(result){
           return (
               <tbody>
                    <tr>
                        <td><input type="radio" name="site_name" 
                                   value={result.SITE_NAME} 
                                   checked={this.state.site === result.SITE_NAME} 
                                   onChange={this.onSiteChanged} />{result.SITE_NAME}</td>
                        <td><input type="radio" name="address" 
                                   value={result.ADDRESS}  
                                   checked={this.state.address === result.ADDRESS} 
                                   onChange={this.onAddressChanged} />{result.ADDRESS}</td>
                    </tr>
               </tbody>
           );
       }, this);
       return (
           <table className="table">
               <thead>
                   <tr>
                       <th>Name</th>
                       <th>Address</th>
                   </tr>
               </thead>
                {resultRows}
               <tfoot>
                   <tr>
                       <td>chosen site name {this.state.site} </td>
                       <td>chosen address {this.state.address} </td>
                   </tr>
               </tfoot>
           </table>
       );
  }
});

jsbin


3
นั่นมีประโยชน์มาก ขอบคุณ สิ่งที่ผมไม่เข้าใจคือบิตเพียงใต้}, this); </tbody>มันคืออะไรและมันทำอะไร? ฉันสังเกตเห็นว่ารหัสนั้นขัดข้อง
Houman

3
thisเป็นบริบทส่งผ่านไปยังฟังก์ชั่นmap มันเป็นการแก้ไขโดย @FakeRainBrigand ดีมาก! ถ้าไม่มีthisฟังก์ชั่นแผนที่ของคุณก็จะอ้างถึงwindowซึ่งไม่มีความคิดว่าstateมันจะเกี่ยวกับอะไร
ChinKang

8
นี้thisเคล็ดลับคือไม่จำเป็นถ้าคุณใช้ ES6 ลูกศรแทนของฟังก์ชั่นปกติ เช่นvar resultRows = this.props.data.map((result) => { ... });ฉันเพียงแค่พูดถึงเพราะ React-ers มักใช้รูปแบบการแพร่สัญญาณ (สำหรับ JSX) อยู่แล้วดังนั้น ES6 จึงเข้าถึงได้ง่าย
Tom

1
การใช้สองฟังก์ชั่นเพื่อรับค่าของปุ่มตัวเลือกนั้นดูเหมือนคลุมเครือและไม่จำเป็น คุณสามารถนิยามฟังก์ชันหนึ่งฟังก์ชันได้บางทีonInputChange (e) {this.setState({ [e.target.name]: e.target.value }); }
xplorer1

109

นี่เป็นวิธีที่ง่ายที่สุดในการใช้ปุ่มตัวเลือกในการตอบสนอง js

class App extends React.Component {
  
  setGender(event) {
    console.log(event.target.value);
  }
  
  render() {
    return ( 
      <div onChange={this.setGender.bind(this)}>
        <input type="radio" value="MALE" name="gender"/> Male
        <input type="radio" value="FEMALE" name="gender"/> Female
      </div>
     )
  }
}

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

แก้ไข

คุณสามารถใช้ฟังก์ชั่นลูกศรแทนการผูก แทนที่รหัสข้างต้นเป็น

<div onChange={event => this.setGender(event)}>

สำหรับการใช้ค่าเริ่มต้นdefaultCheckedเช่นนี้

<input type="radio" value="MALE" defaultChecked name="gender"/> Male

6
ฉันเชื่อว่า.bind(this)จะสร้างฟังก์ชั่นใหม่ทุกครั้ง ซึ่งหมายความว่าเมื่อตรวจสอบการตอบสนองเพื่อดูว่ามีอะไรเปลี่ยนแปลงใน DOM เสมือนส่วนประกอบนี้จะแตกต่างกันเสมอและจำเป็นต้องแสดงผลซ้ำ
WoodenKitty

1
ฟังก์ชั่นใหม่ของการเรนเดอร์แต่ละตัวจะเป็นปัญหาก็ต่อเมื่อส่งผ่านฟังก์ชั่นนี้ลงไปเป็นอุปกรณ์ประกอบฉากให้กับองค์ประกอบย่อย ในกรณีดังกล่าวส่วนประกอบของเด็กที่ได้รับอุปกรณ์ประกอบฉากอาจแสดงโดยไม่จำเป็น องค์ประกอบหลักจะดี
Mark McKelvy

5
สำหรับฉันนี่ใช้งานได้เพียงครั้งเดียวสำหรับการคลิกวิทยุทุกรายการที่ใช้ชื่อเดียวกัน ตัวอย่างเช่นฉันมีวิทยุสองตัวที่มีnameเสาเหมือนกัน พวกเขาทั้งคู่อยู่ใน div ที่มีonChangeตัวจัดการตามที่อธิบายไว้ในคำตอบนี้ ฉันคลิกที่วิทยุตัวแรกเหตุการณ์ถูกยิง ฉันคลิกวิทยุตัวที่สองเหตุการณ์ถูกไล่ออก ครั้งที่สามเป็นต้นไปไม่มีเหตุการณ์ใดถูกยิง ทำไม?
Squrler

4
@ Saahithyan ฉันมีแอททริบิวชื่อเดียวกันกับวิทยุทั้งหมด กลับกลายเป็นว่าฉันจำเป็นต้องใส่ตัวจัดการ onClick ไปที่อินพุตวิทยุแทนที่จะเป็นตัวจัดการ onChange นั่นเป็นการหลอกลวง
Squrler

3
ฉันเห็นด้วยกับ @Squrler - ด้วย onChange ตัวจัดการจะยิงเพียงครั้งเดียวสำหรับปุ่มตัวเลือกแต่ละปุ่มที่รวมอยู่ใน div ด้วย onClick มันทำงานได้หลายครั้ง ไม่แน่ใจว่าทำไมถึงถูกเปรียบเทียบกับตัวอย่างข้อมูลของคุณ ...
JESii

25

ขึ้นอยู่กับสิ่งที่React Docs พูด :

การจัดการหลายอินพุต เมื่อคุณต้องการจัดการองค์ประกอบการป้อนข้อมูลที่มีการควบคุมหลายรายการคุณสามารถเพิ่มแอตทริบิวต์ชื่อให้กับแต่ละองค์ประกอบและให้ฟังก์ชันตัวจัดการเลือกสิ่งที่ต้องทำตามค่าของ event.target.name

ตัวอย่างเช่น:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {};
  }

  handleChange = e => {
    const { name, value } = e.target;

    this.setState({
      [name]: value
    });
  };

  render() {
    return (
      <div className="radio-buttons">
        Windows
        <input
          id="windows"
          value="windows"
          name="platform"
          type="radio"
          onChange={this.handleChange}
        />
        Mac
        <input
          id="mac"
          value="mac"
          name="platform"
          type="radio"
          onChange={this.handleChange}
        />
        Linux
        <input
          id="linux"
          value="linux"
          name="platform"
          type="radio"
          onChange={this.handleChange}
        />
      </div>
    );
  }
}

ลิงก์ไปที่ตัวอย่าง: https://codesandbox.io/s/6l6v9p0qkr

ในตอนแรกไม่มีการเลือกปุ่มตัวเลือกเลยดังนั้นจึงthis.stateเป็นวัตถุว่างเปล่า แต่เมื่อใดก็ตามที่เลือกปุ่มตัวเลือกthis.stateจะได้รับคุณสมบัติใหม่พร้อมชื่อของอินพุตและค่าของมัน มันจะทำให้ง่ายขึ้นเพื่อตรวจสอบว่าผู้ใช้เลือกปุ่มตัวเลือกเช่น

const isSelected = this.state.platform ? true : false;

แก้ไข:

ด้วยเวอร์ชัน 16.7-alpha ของ React มีข้อเสนอสำหรับสิ่งที่เรียกว่าhooksซึ่งจะช่วยให้คุณทำสิ่งนี้ได้ง่ายขึ้น:

ในตัวอย่างด้านล่างมีปุ่มตัวเลือกสองกลุ่มในองค์ประกอบที่ใช้งานได้ ถึงกระนั้นพวกเขายังควบคุมอินพุต:

function App() {
  const [platformValue, plaftormInputProps] = useRadioButtons("platform");
  const [genderValue, genderInputProps] = useRadioButtons("gender");
  return (
    <div>
      <form>
        <fieldset>
          Windows
          <input
            value="windows"
            checked={platformValue === "windows"}
            {...plaftormInputProps}
          />
          Mac
          <input
            value="mac"
            checked={platformValue === "mac"}
            {...plaftormInputProps}
          />
          Linux
          <input
            value="linux"
            checked={platformValue === "linux"}
            {...plaftormInputProps}
          />
        </fieldset>
        <fieldset>
          Male
          <input
            value="male"
            checked={genderValue === "male"}
            {...genderInputProps}
          />
          Female
          <input
            value="female"
            checked={genderValue === "female"}
            {...genderInputProps}
          />
        </fieldset>
      </form>
    </div>
  );
}

function useRadioButtons(name) {
  const [value, setState] = useState(null);

  const handleChange = e => {
    setState(e.target.value);
  };

  const inputProps = {
    name,
    type: "radio",
    onChange: handleChange
  };

  return [value, inputProps];
}

ตัวอย่างการทำงาน: https://codesandbox.io/s/6l6v9p0qkr


20

ทำให้ส่วนประกอบวิทยุเป็นองค์ประกอบที่เป็นใบ้และส่งผ่านอุปกรณ์ประกอบฉากไปยังจากผู้ปกครอง

import React from "react";

const Radiocomponent = ({ value, setGender }) => ( 
  <div onChange={setGender.bind(this)}>
    <input type="radio" value="MALE" name="gender" defaultChecked={value ==="MALE"} /> Male
    <input type="radio" value="FEMALE" name="gender" defaultChecked={value ==="FEMALE"}/> Female
  </div>
);

export default Radiocomponent;

2
ง่ายต่อการทดสอบเนื่องจากเป็นส่วนประกอบดัมพ์เป็นฟังก์ชั่นที่บริสุทธิ์
Khalid Azam

7

แค่ไอเดียที่นี่: เมื่อพูดถึงอินพุตวิทยุใน React ฉันมักจะทำให้พวกเขาทั้งหมดในวิธีที่แตกต่างกันซึ่งถูกกล่าวถึงในคำตอบก่อนหน้า

หากสามารถช่วยใครก็ตามที่ต้องการแสดงปุ่มตัวเลือกมากมาย:

import React from "react"
import ReactDOM from "react-dom"

// This Component should obviously be a class if you want it to work ;)

const RadioInputs = (props) => {
  /*
    [[Label, associated value], ...]
  */
  
  const inputs = [["Male", "M"], ["Female", "F"], ["Other", "O"]]
  
  return (
    <div>
      {
        inputs.map(([text, value], i) => (
	  <div key={ i }>
	    <input type="radio"
              checked={ this.state.gender === value } 
	      onChange={ /* You'll need an event function here */ } 
	      value={ value } /> 
    	    { text }
          </div>
        ))
      }
    </div>
  )
}

ReactDOM.render(
  <RadioInputs />,
  document.getElementById("root")
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="root"></div>


1
มันเยี่ยมมาก แห้งมากและทำสิ่งที่ดี ฉันจะใช้วัตถุสำหรับแต่ละตัวเลือก แต่มันเป็นเรื่องของการตั้งค่าฉันเดา
nbkhope

@nbkhope ถ้าฉันต้องเขียนใหม่ฉันจะใช้ object แทนด้วย! :)
Arnaud

ตรวจสอบบรรทัดนี้: checked={ this.state.gender === value }. thisส่วนประกอบการทำงานไม่ได้
Abraham Hernandez

6
import React, { Component } from "react";

class RadionButtons extends Component {
  constructor(props) {
    super(props);

    this.state = {
      // gender : "" , // use this one if you don't wanna any default value for gender
      gender: "male" // we are using this state to store the value of the radio button and also use to display the active radio button
    };

    this.handleRadioChange = this.handleRadioChange.bind(this);  // we require access to the state of component so we have to bind our function 
  }

  // this function is called whenever you change the radion button 
  handleRadioChange(event) {
      // set the new value of checked radion button to state using setState function which is async funtion
    this.setState({
      gender: event.target.value
    });
  }


  render() {
    return (
      <div>
        <div check>
          <input
            type="radio"
            value="male" // this is te value which will be picked up after radio button change
            checked={this.state.gender === "male"} // when this is true it show the male radio button in checked 
            onChange={this.handleRadioChange} // whenever it changes from checked to uncheck or via-versa it goes to the handleRadioChange function
          />
          <span
           style={{ marginLeft: "5px" }} // inline style in reactjs 
          >Male</span>
        </div>
        <div check>
          <input
            type="radio"
            value="female"
            checked={this.state.gender === "female"}
            onChange={this.handleRadioChange}
          />
          <span style={{ marginLeft: "5px" }}>Female</span>
        </div>
      </div>
    );
  }
}
export default RadionButtons;

1
รหัสของคุณใช้งานได้ แต่คุณควรอธิบายให้ฟังหน่อย
Rahul Sharma

หมายเหตุ : อย่าใช้ป้องกันการผิดพลาดในตัวจัดการ onChange เนื่องจากป้องกันการตั้งค่าที่ตรวจสอบกับคอมโพเนนต์ DOM
AlexNikonov

2

การคลิกปุ่มตัวเลือกควรทำให้เกิดเหตุการณ์ที่:

  1. เรียก setState หากคุณต้องการให้ความรู้การเลือกเป็นท้องถิ่นหรือ
  2. โทรกลับที่ได้รับการส่งผ่านจากด้านบน self.props.selectionChanged(...)

ในกรณีแรกการเปลี่ยนแปลงคือสถานะจะทริกเกอร์การแสดงผลซ้ำและคุณสามารถทำได้
<td>chosen site name {this.state.chosenSiteName} </td>

ในกรณีที่สองแหล่งที่มาของการติดต่อกลับจะอัปเดตสิ่งต่าง ๆ เพื่อให้แน่ใจว่าลงบรรทัดอินสแตนซ์ SearchResult ของคุณจะได้เลือกไซต์ชื่อและเลือกที่อยู่ที่ตั้งไว้ในอุปกรณ์ประกอบฉาก


2

เพื่อสร้างให้ชินกังพูดเพื่อคำตอบของเขาฉันมีแนวทางที่แห้งกว่าและใน es6 สำหรับผู้ที่สนใจ:

class RadioExample extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      selectedRadio: 'public'
    };
  }

  handleRadioChange = (event) => {
    this.setState({
      selectedRadio: event.currentTarget.value
    })
  };

  render() {
    return (
      <div className="radio-row">
        <div className="input-row">
          <input
            type="radio"
            name="public"
            value="public"
            checked={this.state.selectedRadio === 'public'}
            onChange={this.handleRadioChange}
          />
          <label htmlFor="public">Public</label>
        </div>
        <div className="input-row">
          <input
            type="radio"
            name="private"
            value="private"
            checked={this.state.selectedRadio === 'private'}
            onChange={this.handleRadioChange}
          />
          <label htmlFor="private">Private</label>
        </div>
      </div>
    )
  }
}

ยกเว้นอันนี้จะมีค่าการตรวจสอบเริ่มต้น


1

ฉันยังสับสนในเรื่องวิทยุการใช้งานช่องทำเครื่องหมาย สิ่งที่เราต้องการคือฟังเหตุการณ์การเปลี่ยนแปลงของวิทยุจากนั้นตั้งค่าสถานะ ฉันทำตัวอย่างเล็ก ๆ ของการเลือกเพศ

/*
 * A simple React component
 */
class App extends React.Component {
  constructor(params) {
     super(params) 
     // initial gender state set from props
     this.state = {
       gender: this.props.gender
     }
     this.setGender = this.setGender.bind(this)
  }
  
  setGender(e) {
    this.setState({
      gender: e.target.value
    })
  }
  
  render() {
    const {gender} = this.state
    return  <div>
        Gender:
        <div>
          <input type="radio" checked={gender == "male"} 
onClick={this.setGender} value="male" /> Male
          <input type="radio" checked={gender == "female"} 
onClick={this.setGender} value="female"  /> Female
        </div>
        { "Select Gender: " } {gender}
      </div>;
  }
}

/*
 * Render the above component into the div#app
 */
ReactDOM.render(<App gender="male" />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>


0

Bootstrap พวกเราทำแบบนี้:


export default function RadioButton({ onChange, option }) {
    const handleChange = event => {
        onChange(event.target.value)
    }

    return (
        <>
            <div className="custom-control custom-radio">
                <input
                    type="radio"
                    id={ option.option }
                    name="customRadio"
                    className="custom-control-input"
                    onChange={ handleChange }
                    value = { option.id }
                    />
                    <label
                        className="custom-control-label"
                        htmlFor={ option.option }
                        >
                        { option.option }
                    </label>
            </div>
        </>
    )
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.