Dapatkan data formulir di ReactJS


200

Saya memiliki bentuk sederhana dalam renderfungsi saya , seperti:

render : function() {
      return (
        <form>
          <input type="text" name="email" placeholder="Email" />
          <input type="password" name="password" placeholder="Password" />
          <button type="button" onClick={this.handleLogin}>Login</button>
        </form>
      );
    },
handleLogin: function() {
   //How to access email and password here ?
}

Apa yang harus saya tulis di handleLogin: function() { ... }untuk mengakses Emaildan Passwordbidang saya?


11
@sallallen Omong kosong apa ini? Penanya dapat membuat SPA dan mungkin tidak ingin formulir dikirimkan seperti formulir HTML biasa. Jika mereka menginginkan ini maka mereka akan mendefinisikan suatu tindakan dan menghapus event handler.
developerbmw

6
Catatan: Anda harus menangani onSubmitformulir daripada klik tombol - dengan cara ini Anda juga akan menangani pengguna yang mengirimkan formulir dengan menekan enter.
developerbmw

10
A <form>dengan <button>atau <input>dengan type=submitakan dikirimkan ketika pengguna menekan Enter di salah satu formulir <input type=text>. Jika Anda mengandalkan onClicktombol, pengguna harus mengklik tombol atau memfokuskannya dan tekan Enter / bilah spasi. Menggunakan onSubmitakan memungkinkan kedua kasus penggunaan. Ketika formulir tidak mendukung Enter untuk mengirim, mereka bisa merasa rusak.
Ross Allen

Jawaban:


167

Gunakan changeperistiwa pada input untuk memperbarui status komponen dan mengaksesnya di handleLogin:

handleEmailChange: function(e) {
   this.setState({email: e.target.value});
},
handlePasswordChange: function(e) {
   this.setState({password: e.target.value});
},
render : function() {
      return (
        <form>
          <input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleEmailChange} />
          <input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handlePasswordChange}/>
          <button type="button" onClick={this.handleLogin}>Login</button>
        </form>);
},
handleLogin: function() {
    console.log("EMail: " + this.state.email);
    console.log("Password: " + this.state.password);
}

Biola yang bekerja .

Baca juga dokumen, ada seluruh bagian yang didedikasikan untuk penanganan formulir: Formulir

Sebelumnya Anda juga bisa menggunakan mixin pembantu dua arah penyatuan data React untuk mencapai hal yang sama, tetapi sekarang sudah tidak digunakan lagi karena menetapkan nilai dan mengubah penangan (seperti di atas):

var ExampleForm = React.createClass({
  mixins: [React.addons.LinkedStateMixin],
  getInitialState: function() {
    return {email: '', password: ''};
  },
  handleLogin: function() {
    console.log("EMail: " + this.state.email);
    console.log("Password: " + this.state.password);
  },
  render: function() {
    return (
      <form>
        <input type="text" valueLink={this.linkState('email')} />
        <input type="password" valueLink={this.linkState('password')} />
        <button type="button" onClick={this.handleLogin}>Login</button>
      </form>
    );
  }
});

Dokumentasi ada di sini: Pembantu Pengikat Dua Arah .


3
Untuk meniru dengan benar fungsionalitas valueLink, contoh pertama Anda harus mengatur valueelemen input. Tanpa itu, nilai-nilai "tidak terkendali" dalam istilah Bereaksi. <input ... value={this.state.password}>.
Ross Allen

10
Anda juga dapat menggunakan onSubmit dengan formulir alih-alih onClick dengan tombol
sai

60
Mengapa menggunakan status untuk setiap elemen formulir? Adakah yang mengira ini adalah pola yang buruk?
eveevans

6
Sepertinya valueLink sudah usang
Matt Broekhuis

3
Bukankah ini menyimpan kata sandi dalam teks yang jelas di sisi klien sepanjang waktu? Itu tampaknya tidak benar-benar sesuai untuk bidang kata sandi.
NewbiZ

166

Ada beberapa cara untuk melakukan ini:

1) Dapatkan nilai dari berbagai elemen bentuk berdasarkan indeks

handleSubmit = (event) => {
  event.preventDefault();
  console.log(event.target[0].value)
}

2) Menggunakan atribut nama dalam html

handleSubmit = (event) => {
  event.preventDefault();
  console.log(event.target.elements.username.value) // from elements property
  console.log(event.target.username.value)          // or directly
}

<input type="text" name="username"/>

3) Menggunakan referensi

handleSubmit = (event) => {
  console.log(this.inputNode.value)
}

<input type="text" name="username" ref={node => (this.inputNode = node)}/>

Contoh lengkap

class NameForm extends React.Component {
  handleSubmit = (event) => {
    event.preventDefault()
    console.log(event.target[0].value)
    console.log(event.target.elements.username.value)
    console.log(event.target.username.value)
    console.log(this.inputNode.value)
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input
            type="text"
            name="username"
            ref={node => (this.inputNode = node)}
          />
        </label>
        <button type="submit">Submit</button>
      </form>
    )
  }
}

1
Ini jawaban yang fantastis. Terima kasih telah mendaftar beberapa cara untuk melakukan ini.
Beau Smith

Opsi 2 tidak berfungsi untuk saya. Tidak ada properti "elemen" atau "nama pengguna", meskipun nama input saya adalah "nama pengguna"
Madacol

@ Madacol ini mungkin terjadi adalah Anda memiliki beberapa input dengan nama yang sama
Aliaksandr Sushkevich

45

Pendekatan alternatif adalah dengan menggunakan refatribut dan referensi nilai-nilai this.refs. Ini adalah contoh sederhana:

render: function() {
    return (<form onSubmit={this.submitForm}>
        <input ref="theInput" />
    </form>);
},
submitForm: function(e) {
    e.preventDefault();
    alert(React.findDOMNode(this.refs.theInput).value);
}

Info lebih lanjut dapat ditemukan di React docs: https://facebook.github.io/react/docs/more-about-refs.html#the-ref-string-attribute

Karena banyak alasan yang dijelaskan dalam Bagaimana cara menggunakan tombol radio di Bereaksi? pendekatan ini tidak selalu yang terbaik, tetapi memang menyajikan alternatif yang berguna dalam beberapa kasus sederhana.


1
Apakah solusi ini benar-benar lebih baik dan tidak tersedia pada waktu pertanyaan, atau ini cara yang "jelek"?
Wagner Leonardi

4
sebenarnya Anda tidak perlu React.findDOMNode this.refs.theInput sudah menjadi simpul html
Fareed Alnamrouti

23

Cara mudah untuk berurusan dengan referensi:

class UserInfo extends React.Component {

  constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleSubmit(e) {
    e.preventDefault();
    
    const formData = {};
    for (const field in this.refs) {
      formData[field] = this.refs[field].value;
    }
    console.log('-->', formData);
  }

  render() {
    return (
        <div>
          <form onSubmit={this.handleSubmit}>
            <input ref="phone" className="phone" type='tel' name="phone"/>
            <input ref="email" className="email" type='tel' name="email"/>
            <input type="submit" value="Submit"/>
          </form>
        </div>
    );
  }
}

export default UserInfo;


2
Metode ini suatu hari nanti akan ditinggalkan. Referensi hanya digunakan dengan callback dan bukan string. Untuk detail lebih lanjut: facebook.github.io/react/docs/refs-and-the-dom.html
David Labbe

Keren! :) Saya suka menggunakan Object.keys()diikuti untuk map()seperti ini:Object.keys(this.refs).map(field => formData[field] = this.refs[field].value)
Francis Rodrigues

Ya, ref string sudah ditinggalkan. Cara yang lebih baik untuk melakukannya sekarang adalah dengan menggunakan panggilan balik onChange. Jika Anda masih ingin menggunakan referensi, Anda bisa menggunakan sintaks ini:<input type="text" ref={(input) => { this.textInput = input; }} />
E. Fortes

I @ E.Fortes, bisakah Anda menjelaskan metode panggilan balik onChange? Terima kasih banyak jika mau. Tolong beri tag pada saya agar saya akan diberi tahu tentang jawaban Anda.
Simona Adriani

cara sederhana adalah (maaf formatter kode tidak berfungsi): class NameForm extends React.Component {constructor (props) {super (props); this.state = {value: ''}; this.handleChange = this.handleChange.bind (ini); } handleChange (event) {this.setState ({value: event.target.value}); } render () {return (<form> <label> Nama: <input type = "text" value = {this.state.value} onChange = {this.handleChange} /> </label> </form>); }}
E. Fortes

23

Menambahkan jawaban Michael Schock:

class MyForm extends React.Component {
  constructor() {
    super();
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleSubmit(event) {
    event.preventDefault();
    const data = new FormData(event.target);

    console.log(data.get('email')); // reference by form input's `name` tag

    fetch('/api/form-submit-url', {
      method: 'POST',
      body: data,
    });
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label htmlFor="username">Enter username</label>
        <input id="username" name="username" type="text" />

        <label htmlFor="email">Enter your email</label>
        <input id="email" name="email" type="email" />

        <label htmlFor="birthdate">Enter your birth date</label>
        <input id="birthdate" name="birthdate" type="text" />

        <button>Send data!</button>
      </form>
    );
  }
}

Lihat artikel Medium ini: Cara Menangani Formulir dengan Just React

Metode ini mendapatkan data formulir hanya ketika tombol Kirim ditekan. IMO jauh lebih bersih!


Jawaban sempurna. 👌
Michal

16

Anda bisa mengganti onClickevent handler pada tombol ke onSubmithandler pada form:

render : function() {
      return (
        <form onSubmit={this.handleLogin}>
          <input type="text" name="email" placeholder="Email" />
          <input type="password" name="password" placeholder="Password" />
          <button type="submit">Login</button>
        </form>
      );
    },

Kemudian Anda dapat menggunakan FormDatauntuk mem-parsing formulir (dan membangun objek JSON dari entri jika Anda mau).

handleLogin: function(e) {
   const formData = new FormData(e.target)
   const user = {}

   e.preventDefault()

   for (let entry of formData.entries()) {
       user[entry[0]] = entry[1]
   }

   // Do what you will with the user object here
}

Menjalankan ini plus 'console.log (pengguna);' memberikan objek tanpa nilai yang dapat digunakan! Ada pendapat?
M pada

@MahdiRafatjah ¯ \ _ (ツ) _ / ¯ - ini berfungsi dalam biola ini: jsfiddle.net/mschock/exvko2Lf
Michael Schock

seorang teman saya merujuk saya untuk bereaksi dokumen dan mereka melakukannya seperti ini reactjs.org/docs/forms.html#controlled-components
M pada

1
bagus, itu tampak jauh lebih bersih =)
Michael Schock

13

Saya akan menyarankan pendekatan berikut:

import {Autobind} from 'es-decorators';

export class Form extends Component {

    @Autobind
    handleChange(e) {
        this.setState({[e.target.name]: e.target.value});
    }

    @Autobind
    add(e) {
        e.preventDefault();
        this.collection.add(this.state);
        this.refs.form.reset();
    }

    shouldComponentUpdate() {
        return false;
    }

    render() {
        return (
            <form onSubmit={this.add} ref="form">
                <input type="text" name="desination" onChange={this.handleChange}/>
                <input type="date" name="startDate" onChange={this.handleChange}/>
                <input type="date" name="endDate" onChange={this.handleChange}/>
                <textarea name="description" onChange={this.handleChange}/>
                <button type="submit">Add</button>
            </form>
        )
    }

}

Jika Anda tidak merender komponen, bagaimana Anda dapat mengatur nilai setiap elemen sesuai dengan kondisi saat ini? mis. "value = {this.state. destination}". Anda juga tidak dapat menjalankan validasi reaksi pada formulir jika Anda tidak
merendernya kembali

13

Jika semua input / teks Anda memiliki nama, maka Anda dapat memfilter semua dari event.target:

onSubmit(event){
  const fields = Array.prototype.slice.call(event.target)
      .filter(el => el.name)
      .reduce((form, el) => ({
        ...form,
        [el.name]: el.value,
      }), {})
}

Bentuk yang benar-benar tidak terkendali 😊 tanpa metode, nilai, nilai defaultChange ...


12

Bagi mereka yang tidak ingin menggunakan ref dan mengatur ulang negara dengan OnChangeacara, Anda bisa menggunakan pegangan OnSubmit sederhana dan loop melalui FormDataobjek. Contoh ini menggunakan React Hooks:

const LoginPage = () =>{
    const handleSubmit = (event) => {
        const formData = new FormData(event.target);
        event.preventDefault();
        for (var [key, value] of formData.entries()) {
            console.log(key, value);
        }
    }

    return (
        <div>
        <form onSubmit={
        handleSubmit
        }

        >
        <input type="text" name="username" placeholder="Email" />
        <input type="password" name="password"
        placeholder="Password" />
        <button type="submit">Login</button>
        </form>
        </div>)
        }

Jawaban yang bagus, tetapi sebuah nitpick bisa Anda hilangkan dengan solusi sempurna jika tidak!
Louis345

5

Juga, ini bisa digunakan juga.

handleChange: function(state,e) {
  this.setState({[state]: e.target.value});
},
render : function() {
  return (
    <form>
      <input type="text" name="email" placeholder="Email" value={this.state.email} onChange={this.handleChange.bind(this, 'email')} />
      <input type="password" name="password" placeholder="Password" value={this.state.password} onChange={this.handleChange.bind(this, 'password')}/>
      <button type="button" onClick={this.handleLogin}>Login</button>
    </form>
  );
},
handleLogin: function() {
  console.log("EMail: ", this.state.email);
  console.log("Password: ", this.state.password);
}

4
Harap sertakan penjelasan mengapa jawaban ini adalah cara yang benar untuk dilakukan.
Tim Hutchison

1
Saya hanya menggunakan satu metode untuk mengubah bentuk teks
Yurii Kosygin

Kata sandi dapat dilihat pada alat dev reaksi, sedikit masalah keamanan?
Neil

5

Berikan masukan Anda seperti ini

<input type="text" name="email" placeholder="Email" ref="email" />
<input type="password" name="password" placeholder="Password" ref="password" />

maka Anda dapat mengaksesnya di handleLogin Anda seperti soo

handleLogin: function(e) {
   e.preventDefault();
    console.log(this.refs.email.value)
    console.log(this.refs.password.value)
}

5

Contoh yang lebih jelas dengan es6 destructing

class Form extends Component {
    constructor(props) {
        super(props);
        this.state = {
            login: null,
            password: null,
            email: null
        }
    }

    onChange(e) {
        this.setState({
            [e.target.name]: e.target.value
        })
    }

    onSubmit(e) {
        e.preventDefault();
        let login = this.state.login;
        let password = this.state.password;
        // etc
    }

    render() {
        return (
            <form onSubmit={this.onSubmit.bind(this)}>
                <input type="text" name="login" onChange={this.onChange.bind(this)} />
                <input type="password" name="password" onChange={this.onChange.bind(this)} />
                <input type="email" name="email" onChange={this.onChange.bind(this)} />
                <button type="submit">Sign Up</button>
            </form>
        );
    }
}


4

Dalam banyak peristiwa dalam javascript, kita memiliki eventyang memberikan objek termasuk peristiwa apa yang terjadi dan apa nilainya, dll ...

Itulah yang kami gunakan dengan formulir di ReactJs juga ...

Jadi dalam kode Anda, Anda mengatur negara ke nilai baru ... sesuatu seperti ini:

class UserInfo extends React.Component {

  constructor(props) {
    super(props);
    this.handleLogin = this.handleLogin.bind(this);
  }

  handleLogin(e) {
    e.preventDefault();
    for (const field in this.refs) {
      this.setState({this.refs[field]: this.refs[field].value});
    }
  }

  render() {
    return (
        <div>
          <form onSubmit={this.handleLogin}>
            <input ref="email" type="text" name="email" placeholder="Email" />
            <input ref="password" type="password" name="password" placeholder="Password" />
            <button type="button">Login</button>
          </form>
        </div>
    );
  }
}

export default UserInfo;

Juga ini adalah contoh formulir di Bereaksi v.16, sama seperti referensi untuk formulir yang Anda buat di masa depan:

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

4

Saya menggunakan seperti ini menggunakan status React Component:

<input type="text" name='value' value={this.state.value} onChange={(e) => this.handleChange(e)} />

handleChange(e){
   this.setState({[e.target.name]: e.target.value})
}`

3
 onChange(event){
     console.log(event.target.value);
  }
  handleSubmit(event){ 
    event.preventDefault();
    const formData = {};
      for (const data in this.refs) {
        formData[data] = this.refs[data].value;
      }
    console.log(formData);
  }



 <form onSubmit={this.handleSubmit.bind(this)}>
  <input type="text" ref="username" onChange={this.onChange} className="form-control"/>
  <input type="text" ref="password" onChange={this.onChange} className="form-control"/>
  <button type="submit" className="btn-danger btn-sm">Search</button>
 </form>

Output gambar terlampir di sini


Tolong berikan penjelasan juga.
BlackBeard

2
Saya akan mencoba menjelaskan ini, yang menurut saya brilian. Dalam fungsi handleSubmit () Anda sedang membangun objek (formData) di mana kuncinya adalah atribut 'ref' dari setiap input dalam formulir (pernyataan 'formData [data]'), dan nilainya adalah nilai input dengan atribut 'ref' ini (pernyataan 'this.refs [data] .value'). Dengan 'formData [data] = this.refs [data] .value' Anda sedang membangun objek ini. Anda mengatakan, secara harfiah: formData ['nama pengguna'] = (nilai input nama pengguna) dan formData ['kata sandi'] = (nilai input kata sandi) Output akan menjadi: {user: 'blablabla', kata sandi: 'xxx '}
Simona Adriani

Terima kasih @SimonaAdriani atas penjelasannya.
Milan Panigrahi

2

Ini mungkin membantu pengguna Meteor (v1.3):

render: function() {
    return (
        <form onSubmit={this.submitForm.bind(this)}>
            <input type="text" ref="email" placeholder="Email" />
            <input type="password" ref="password" placeholder="Password" />
            <button type="submit">Login</button>
        </form>
    );
},
submitForm: function(e) {
    e.preventDefault();
    console.log( this.refs.email.value );
    console.log( this.refs.password.value );
}

1
this.submitForm.bind (this) seharusnya hanya: this.submitForm
rekarnar

Kesalahan: Komponen fungsi Stateless tidak dapat memiliki referensi.
holms

Apakah Anda menggunakan Meteor (v1.3)?
Joe L.

1

Untuk meningkatkan pengalaman pengguna; ketika pengguna mengklik tombol kirim, Anda dapat mencoba mendapatkan formulir untuk pertama kali menampilkan pesan pengiriman. Setelah kami menerima tanggapan dari server, ia dapat memperbarui pesan sesuai dengan itu. Kami mencapai ini dalam Bereaksi dengan merantai status. Lihat codepen atau cuplikan di bawah ini:

Metode berikut membuat perubahan status pertama:

handleSubmit(e) {
    e.preventDefault();
    this.setState({ message: 'Sending...' }, this.sendFormData);
}

Segera setelah Bereaksi menunjukkan pesan pengiriman di atas pada layar, ia akan memanggil metode yang akan mengirim data formulir ke server: this.sendFormData (). Untuk kesederhanaan, saya telah menambahkan setTimeout untuk meniru ini.

sendFormData() {
  var formData = {
      Title: this.refs.Title.value,
      Author: this.refs.Author.value,
      Genre: this.refs.Genre.value,
      YearReleased: this.refs.YearReleased.value};
  setTimeout(() => { 
    console.log(formData);
    this.setState({ message: 'data sent!' });
  }, 3000);
}

Di Bereaksi, metode this.setState () merender komponen dengan properti baru. Jadi, Anda juga dapat menambahkan beberapa logika dalam metode render () dari komponen formulir yang akan berperilaku berbeda tergantung pada jenis respons yang kami dapatkan dari server. Misalnya:

render() {
  if (this.state.responseType) {
      var classString = 'alert alert-' + this.state.type;
      var status = <div id="status" className={classString} ref="status">
                     {this.state.message}
                   </div>;
  }
return ( ...

codepen


1

Jika Anda memiliki beberapa kemunculan nama elemen, maka Anda harus menggunakan forEach ().

html

  <input type="checkbox" name="delete" id="flizzit" />
  <input type="checkbox" name="delete" id="floo" />
  <input type="checkbox" name="delete" id="flum" />
  <input type="submit" value="Save"  onClick={evt => saveAction(evt)}></input>

js

const submitAction = (evt) => {
  evt.preventDefault();
  const dels = evt.target.parentElement.delete;
  const deleted = [];
  dels.forEach((d) => { if (d.checked) deleted.push(d.id); });
  window.alert(deleted.length);
};

Perhatikan bahwa dels dalam hal ini adalah RadioNodeList, bukan array, dan bukan Iterable. ForEach () adalah metode bawaan dari kelas daftar. Anda tidak akan dapat menggunakan peta () atau mengurangi () di sini.


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.