Bagaimana cara menggunakan tombol radio di ReactJS?

204

Saya baru mengenal ReactJS, maaf jika ini tidak aktif. Saya memiliki komponen yang membuat beberapa baris tabel sesuai dengan data yang diterima.

Setiap sel dalam kolom memiliki kotak centang radio. Karenanya pengguna dapat memilih satu site_namedan satu addressdari baris yang ada. Seleksi harus ditunjukkan dalam catatan kaki. Dan di situlah saya terjebak.

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

Di jQuery saya bisa melakukan sesuatu seperti $("input[name=site_name]:checked").val()mendapatkan pemilihan satu jenis kotak centang radio dan memasukkannya ke sel footer pertama.

Tetapi tentunya harus ada cara Reactjs, yang saya benar-benar hilang? Terimakasih banyak

Houman
sumber
3
inputelemen tidak memiliki konten. Jadi <input>content</input>tidak masuk akal dan tidak valid. Anda mungkin mau <label><input />content</label>.
Oriol
1
tidakkah tombol radio harus memiliki nama yang sama dengan nilai yang berbeda untuk bekerja?
pgee70

Jawaban:

209

Setiap perubahan pada rendering harus diubah melalui stateatau props( react doc ).

Jadi di sini saya mendaftarkan acara input, dan kemudian mengubah state, yang kemudian akan memicu render untuk ditampilkan di footer.

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

ChinKang
sumber
3
Itu sangat berguna. Terima kasih. Yang tidak saya mengerti adalah sedikit }, this);di bawahnya </tbody>. Apa itu dan apa fungsinya? Saya perhatikan tanpa itu kode crash.
Houman
3
The thisadalah konteks dilewatkan ke mapfungsi . Itu hasil edit oleh @FakeRainBrigand, tangkapan bagus! Tanpanya, thisfungsi peta Anda akan merujuk ke window, yang tidak tahu tentang apa stateitu
ChinKang
8
Ini thistrik tidak diperlukan jika Anda menggunakan ES6 panah bukan fungsi biasa. Misalnya: var resultRows = this.props.data.map((result) => { ... });Saya hanya menyebutkannya karena React-ers biasanya sudah menggunakan beberapa bentuk transpilasi (untuk JSX), jadi ES6 biasanya mudah dijangkau.
Tom
1
Menggunakan dua fungsi untuk mendapatkan nilai-nilai tombol radio tampak ambigu dan tidak perlu. Anda bisa mendefinisikan satu fungsi, mungkinonInputChange (e) {this.setState({ [e.target.name]: e.target.value }); }
xplorer1
110

Berikut adalah cara paling sederhana untuk mengimplementasikan tombol radio dalam bereaksi.

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>

Diedit

Anda dapat menggunakan fungsi panah alih-alih mengikat. Ganti kode di atas sebagai

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

Untuk penggunaan nilai default defaultChecked, seperti ini

<input type="radio" value="MALE" defaultChecked name="gender"/> Male
Saahithyan Vigneswaran
sumber
6
Saya percaya .bind(this)akan membuat fungsi baru setiap saat. Ini berarti ketika bereaksi memeriksa untuk melihat apakah ada yang berubah di DOM virtual, komponen ini akan selalu berbeda, dan selalu perlu dirender ulang.
WoodenKitty
1
Fungsi baru pada setiap render hanya akan menjadi masalah jika melewatkan fungsi ini sebagai penyangga untuk komponen anak. Dalam hal itu komponen anak yang menerima alat peraga mungkin membuat tidak perlu. Komponen induk akan baik-baik saja.
Mark McKelvy
5
Bagi saya ini hanya berfungsi sekali untuk mengklik setiap radio yang memiliki nama yang sama. Misalnya, saya punya dua radio yang memiliki nameprop yang sama . Keduanya dibungkus dengan div yang memiliki onChangepawang seperti yang dijelaskan dalam jawaban ini. Saya mengklik radio pertama, sebuah acara dipecat. Saya mengklik radio kedua, sebuah acara dipecat. Namun yang ketiga dan selanjutnya, tidak ada acara yang dipecat. Mengapa?
Squrler
4
@ Saahithyan Saya memiliki atribut nama yang sama dengan semua radio. Ternyata saya harus meletakkan handler onClick ke input radio alih-alih handler onChange. Itu berhasil.
Squrler
3
Saya setuju dengan @Squrler - dengan onChange, pegangan hanya menyala sekali untuk masing-masing tombol radio yang termasuk dalam div. Dengan onClick, ini berfungsi beberapa kali. Tidak yakin mengapa itu dibandingkan dengan cuplikan Anda ...
JESii
25

Berdasarkan apa yang dikatakan React Docs :

Menangani Banyak Input. Saat Anda perlu menangani beberapa elemen input yang dikontrol, Anda dapat menambahkan atribut nama ke setiap elemen dan membiarkan fungsi handler memilih apa yang harus dilakukan berdasarkan nilai event.target.name.

Sebagai contoh:

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

Tautan ke contoh: https://codesandbox.io/s/6l6v9p0qkr

Pada awalnya, tidak ada tombol radio yang dipilih sehingga this.statemerupakan objek kosong, tetapi setiap kali tombol radio dipilih this.statemendapatkan properti baru dengan nama input dan nilainya. Maka memudahkan untuk memeriksa apakah pengguna memilih tombol radio seperti:

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

EDIT:

Dengan React versi 16.7-alpha ada proposal untuk sesuatu yang disebut hooksyang akan membuat Anda melakukan hal-hal semacam ini lebih mudah:

Pada contoh di bawah ini ada dua kelompok tombol radio dalam komponen fungsional. Namun, mereka telah mengendalikan input:

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

Contoh kerja: https://codesandbox.io/s/6l6v9p0qkr

Tomasz Mularczyk
sumber
20

Jadikan komponen radio sebagai komponen bisu dan berikan bantuan dari orangtua.

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;
Khalid Azam
sumber
2
mudah untuk diuji karena komponen dump adalah fungsi murni.
Khalid Azam
7

Hanya sebuah ide di sini: ketika datang ke input radio di Bereaksi, saya biasanya membuat semuanya dengan cara yang berbeda yang disebutkan dalam jawaban sebelumnya.

Jika ini dapat membantu siapa saja yang perlu membuat banyak tombol radio:

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>

Arnaud
sumber
1
Ini bagus. Sangat KERING dan membuat semuanya menyenangkan. Saya akan menggunakan objek untuk setiap opsi, tapi ini masalah preferensi, saya kira.
nbkhope
@ Mbkhope jika saya harus menulis ulang, saya akan menggunakan objek juga! :)
Arnaud
Periksa baris ini: checked={ this.state.gender === value }. Komponen fungsional tidak punya 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;
ABHIJEET KHIRE
sumber
1
Kode Anda berfungsi tetapi Anda juga harus menjelaskannya sedikit
Rahul Sharma
CATATAN : JANGAN gunakan preventDefault di penangan onChange karena mencegah pengaturan diperiksa ke komponen DOM
AlexNikonov
2

Mengklik tombol radio akan memicu acara yang:

  1. panggilan setState, jika Anda hanya ingin pengetahuan pemilihan lokal, atau
  2. memanggil panggilan balik yang telah diteruskan dari atas self.props.selectionChanged(...)

Dalam kasus pertama, perubahan adalah status akan memicu re-render dan Anda dapat melakukannya
<td>chosen site name {this.state.chosenSiteName} </td>

dalam kasus kedua, sumber panggilan balik akan memperbarui hal-hal untuk memastikan bahwa di bawah garis, contoh SearchResult Anda akan memilihSiteName dan selectedAddress yang diatur dalam props itu.

z5h
sumber
2

Untuk membangun di atas kata ChinKang untuk jawabannya, saya memiliki pendekatan yang lebih kering dan dalam es6 bagi mereka yang tertarik:

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

kecuali yang ini akan memiliki nilai diperiksa standar.

Tony Tai Nguyen
sumber
1

Saya juga bingung di radio, implementasi kotak centang. Yang kita butuhkan adalah, dengarkan perubahan acara radio, lalu atur keadaan. Saya telah membuat contoh kecil pemilihan gender.

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

rab
sumber
0

Bootstrap guys, kami melakukannya seperti ini:


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>
        </>
    )
}
Gilbert
sumber