Bagaimana cara mendapatkan nilai bidang input menggunakan ReactJS?

189

Saya memiliki komponen Bereaksi berikut:

export default class MyComponent extends React.Component {

    onSubmit(e) {
        e.preventDefault();
        var title = this.title;
        console.log(title);
    }

    render(){
        return (
            ...
            <form className="form-horizontal">
                ...
                <input type="text" className="form-control" ref={(c) => this.title = c} name="title" />
                ...
            </form>
            ...
            <button type="button" onClick={this.onSubmit} className="btn">Save</button>
            ...
        );
    }

};

Konsol memberi saya undefined- ada ide apa yang salah dengan kode ini?

JoeTidee
sumber
7
this.onSubmit.bind(this);
zerkms
Bagus - ingin menambahkannya sebagai jawaban dan saya akan mencentangnya (?)
JoeTidee
2
bagaimana e.target.valuetanpa ikatan?
omarjmh
1
bukankah e.target.value akan menargetkan tombol, bukan bidang input?
JoeTidee
Anda perlu mengikat onSubmitmetode ke tombol kirim (elemen DOM) ketika diklik (yaitu onClick={this.onSubmit.bind(this)}). Dan jika Anda ingin mengakses nilai input judul dalam formulir yang dapat Anda gunakan onSubmit(event) { const title = event.target.elements.title.value; }.
tfmontague

Jawaban:

10

Anda harus menggunakan konstruktor di bawah kelas MyComponent extends React.Component

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

Maka Anda akan mendapatkan hasil judul

Md. Maidul Islam
sumber
316

Ada tiga jawaban di sini, tergantung pada versi Bereaksi Anda (dipaksa) bekerja, dan apakah Anda ingin menggunakan kait.

Hal pertama yang pertama:

Sangat penting untuk memahami bagaimana React bekerja, sehingga Anda dapat melakukan hal-hal dengan benar (protip: itu sangat layak dijalankan melalui latihan tutorial Bereaksi di situs web React. Ini ditulis dengan baik, dan mencakup semua dasar-dasar dengan cara yang benar-benar menjelaskan cara melakukan sesuatu). "Benar" di sini berarti Anda sedang menulis antarmuka aplikasi yang akan dirender di browser; semua pekerjaan antarmuka terjadi di Bereaksi, bukan di "apa yang Anda terbiasa jika Anda sedang menulis halaman web" (inilah sebabnya React apps adalah "apps", bukan "halaman web").

Aplikasi Bereaksi dibuat berdasarkan dua hal:

  1. properti komponen sebagaimana dideklarasikan oleh orang tua mana pun yang membuat turunan dari komponen itu, yang orang tua dapat memodifikasi sepanjang siklus hidupnya, dan
  2. keadaan internal komponen itu sendiri, yang dapat dimodifikasi sendiri sepanjang siklus hidupnya sendiri.

Apa yang Anda jelas tidak lakukan ketika Anda menggunakan Bereaksi menghasilkan elemen HTML dan kemudian menggunakannya: ketika Anda mengatakan Bereaksi untuk menggunakan <input>, misalnya, Anda tidak membuat elemen input HTML, Anda mengatakan Bereaksi untuk membuat objek input Bereaksi yang terjadi untuk merender sebagai elemen input HTML, dan yang penanganan eventnya melihat, tetapi tidak dikendalikan oleh , event input elemen HTML.

Saat menggunakan Bereaksi, apa yang Anda lakukan adalah membuat elemen UI aplikasi yang menyajikan data (seringkali dapat dimanipulasi) kepada pengguna, dengan interaksi pengguna mengubah status Komponen, yang dapat menyebabkan rerender bagian dari antarmuka aplikasi Anda untuk mencerminkan keadaan baru. Dalam model ini, negara selalu menjadi otoritas terakhir, bukan "perpustakaan UI apa pun yang digunakan untuk membuatnya", yang di web adalah DOM peramban. DOM hampir merupakan renungan dalam model pemrograman ini: itu hanya kerangka UI tertentu yang Bereaksi kebetulan gunakan.

Jadi dalam kasus elemen input, logikanya adalah:

  1. Anda mengetikkan elemen input,
  2. tidak ada yang terjadi pada elemen input Anda, peristiwa itu dicegat oleh Bereaksi dan langsung dibunuh ,
  3. Bereaksi maju acara ke fungsi yang telah Anda atur untuk penanganan acara,
  4. fungsi yang dapat menjadwalkan pembaruan negara,
  5. jika ya, React menjalankan pembaruan status itu (tidak sinkron!) dan akan memicu renderpanggilan setelah pembaruan, tetapi hanya jika pembaruan status mengubah status.
  6. hanya setelah render ini terjadi, UI akan menunjukkan bahwa Anda "mengetik huruf".

Semua itu terjadi dalam hitungan milidetik, jika tidak kurang, jadi sepertinya Anda mengetik ke elemen input dengan cara yang sama seperti "dari hanya menggunakan elemen input pada halaman", tapi itu sama sekali bukan itu terjadi.

Jadi, dengan itu, pada cara mendapatkan nilai dari elemen dalam Bereaksi:

Bereaksi 15 dan di bawah, dengan ES5

Untuk melakukan sesuatu dengan benar, komponen Anda memiliki nilai status, yang ditampilkan melalui bidang input, dan kami dapat memperbaruinya dengan membuat elemen UI mengirim perubahan acara kembali ke komponen:

var Component = React.createClass({
  getInitialState: function() {
    return {
      inputValue: ''
    };
  },

  render: function() {
    return (
      //...
      <input value={this.state.inputValue} onChange={this.updateInputValue}/>
      //...
    );
  },

  updateInputValue: function(evt) {
    this.setState({
      inputValue: evt.target.value
    });
  }
});

Jadi, kami memberi tahu React untuk menggunakan updateInputValuefungsi untuk menangani interaksi pengguna, gunakan setStateuntuk menjadwalkan pembaruan status, dan fakta yang rendermengetuk ke dalam this.state.inputValueberarti bahwa ketika ia merender setelah memperbarui status, pengguna akan melihat teks pembaruan berdasarkan pada apa yang mereka ketik.

tambahan berdasarkan komentar

Mengingat bahwa input UI mewakili nilai status (pertimbangkan apa yang terjadi jika pengguna menutup tab di tengah jalan, dan tab dikembalikan. Apakah semua nilai yang diisi harus dipulihkan? Jika demikian, itu adalah keadaan). Itu mungkin membuat Anda merasa seperti formulir besar membutuhkan puluhan atau bahkan seratus formulir input, tetapi Bereaksi adalah tentang memodelkan UI Anda dengan cara yang dapat dipertahankan: Anda tidak memiliki 100 bidang input independen, Anda memiliki grup input terkait, sehingga Anda menangkap masing-masing grup dalam komponen dan kemudian membangun formulir "master" Anda sebagai kumpulan grup.

MyForm:
  render:
    <PersonalData/>
    <AppPreferences/>
    <ThirdParty/>
     ...

Ini juga lebih mudah dirawat daripada komponen bentuk tunggal raksasa. Membagi kelompok menjadi Komponen dengan pemeliharaan negara, di mana setiap komponen hanya bertanggung jawab untuk melacak beberapa bidang input sekaligus.

Anda juga mungkin merasa "repot" untuk menulis semua kode itu, tetapi itu adalah penghematan yang salah: pengembang-yang-bukan-Anda, termasuk Anda di masa depan, sebenarnya sangat diuntungkan dengan melihat semua input tersebut dihubungkan secara eksplisit, karena itu membuat jalur kode lebih mudah dilacak. Namun, Anda selalu dapat mengoptimalkan. Misalnya, Anda dapat menulis tautan negara

MyComponent = React.createClass({
  getInitialState() {
    return {
      firstName: this.props.firstName || "",
      lastName: this.props.lastName || "" 
      ...: ...
      ...
    }
  },
  componentWillMount() {
    Object.keys(this.state).forEach(n => {
      let fn = n + 'Changed';
      this[fn] = evt => {
        let update = {};
        update[n] = evt.target.value;
        this.setState(update);
      });
    });
  },
  render: function() {
    return Object.keys(this.state).map(n => {
      <input
        key={n} 
        type="text"
        value={this.state[n]}
        onChange={this[n + 'Changed']}/>
    });
  }
});

Tentu saja, ada versi yang disempurnakan dari ini, jadi kunjungi https://npmjs.com dan cari solusi menghubungkan kondisi React yang paling Anda sukai. Open Source kebanyakan tentang menemukan apa yang telah dilakukan orang lain, dan menggunakannya daripada menulis sendiri semuanya dari awal.

Bereaksi 16 (dan 15,5 transisi) dan JS 'modern'

Pada React 16 (dan soft-starting dengan 15.5) createClasspanggilan tidak lagi didukung, dan sintaksis kelas perlu digunakan. Ini mengubah dua hal: sintaksis kelas yang jelas, tetapi juga thispengikatan konteks yang createClassdapat melakukan "gratis", jadi untuk memastikan semuanya tetap berfungsi, pastikan Anda menggunakan notasi "panah gemuk" untuk thiskonteks mempertahankan fungsi anonim di onWhateverpenangan, seperti yang onChangekita digunakan dalam kode di sini:

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

  render() {
    return (
      //...
      <input value={this.state.inputValue} onChange={evt => this.updateInputValue(evt)}/>
      //...
    );
  },

  updateInputValue(evt) {
    this.setState({
      inputValue: evt.target.value
    });
  }
});

Anda mungkin juga pernah melihat orang menggunakan bindkonstruktor mereka untuk semua fungsi penanganan acara mereka, seperti ini:

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

render() {
  return (
    ...
    <element onclick={this.handler}/>
    ...
  );
}

Jangan lakukan itu.

Hampir setiap saat Anda menggunakan bind, pepatah "Anda salah melakukannya" berlaku. Kelas Anda sudah mendefinisikan prototipe objek, dan sudah mendefinisikan konteks instance. Jangan menempatkan binddi atas itu; gunakan penerusan kejadian normal alih-alih menduplikasi semua panggilan fungsi Anda di konstruktor, karena duplikasi itu meningkatkan permukaan bug Anda, dan membuatnya lebih sulit untuk melacak kesalahan karena masalahnya mungkin ada di konstruktor Anda alih-alih di mana Anda memanggil kode Anda. Serta menempatkan beban pemeliharaan pada orang lain yang Anda (miliki atau pilih) untuk bekerja dengannya.

Ya, saya tahu dokumen reaksi mengatakan tidak apa-apa. Bukan, jangan lakukan itu.

Bereaksi 16.8, menggunakan komponen fungsi dengan kait

Pada Bereaksi 16.8 komponen fungsi (yaitu secara harfiah hanya fungsi yang mengambil propsargumen sebagai dapat digunakan seolah-olah itu adalah instance dari kelas komponen, tanpa pernah menulis kelas) juga dapat diberi status, melalui penggunaan kait .

Jika Anda tidak memerlukan kode kelas penuh, dan fungsi instance tunggal akan dilakukan, maka Anda sekarang dapat menggunakan useStatehook untuk mendapatkan sendiri variabel status tunggal, dan fungsi pembaruannya, yang bekerja kira-kira sama dengan contoh di atas, kecuali tanpa yang setStatefungsi panggilan:

import { useState } from 'react';

function myFunctionalComponentFunction() {
  const [input, setInput] = useState(''); // '' is the initial state value
  return (
    <div>
    <label>Please specify:</label>
    <input value={input} onInput={e => setInput(e.target.value)}/>
    </div>
  );
}

Sebelumnya perbedaan tidak resmi antara kelas dan komponen fungsi adalah "komponen fungsi tidak memiliki status", jadi kita tidak dapat menyembunyikannya lagi: perbedaan antara komponen fungsi dan komponen kelas dapat ditemukan tersebar di beberapa halaman dengan sangat baik -dokumen reaksi tertulis (tidak ada jalan pintas penjelasan satu liner untuk dengan mudah disalahartikan untuk Anda!) yang harus Anda baca sehingga Anda tahu apa yang Anda lakukan dan dengan demikian dapat mengetahui apakah Anda memilih yang terbaik (apa pun artinya bagi Anda) solusi untuk memprogram diri Anda sendiri karena masalah yang Anda alami.

Mike 'Pomax' Kamermans
sumber
4
Saya telah membaca beberapa artikel online yang mengatakan bahwa menggunakan terlalu banyak status adalah ide yang buruk. Dalam satu bentuk aplikasi tertentu saya memiliki sekitar 100 bidang formulir. Menentukan fungsi untuk menyelamatkan negara terasa seperti cara sulit yang tidak perlu dalam melakukan sesuatu. Jika saya dapat menggunakan onClick = {this.onSubmit.bind (this)}, ini sepertinya cara yang baik untuk mendapatkan nilai (lalu jika saya mau, atur status komponen) - Saya akan menghargai beberapa komentar tentang ini.
JoeTidee
5
jadi tulis kode yang lebih cerdas. input formulir paling jelas menyatakan (pertimbangkan apa yang terjadi jika pengguna menutup tab di tengah jalan, dan tab dikembalikan. Haruskah semua nilai yang diisi dikembalikan? ya? itu keadaan ), jadi tuliskan sedikit kode pemeliharaan negara. Facebook juga memiliki ratusan nilai formulir, dan solusi mereka untuk kegilaan itu adalah React. Ini bekerja dengan sangat baik. Salah satu cara untuk membuat kode Anda sedikit lebih mudah, sementara masih menggunakan status, adalah dengan menggunakan tautan dua arah , sekali lagi, dijelaskan di situs Bereaksi. Layak dibaca! =)
Mike 'Pomax' Kamermans
2
Perhatikan juga bahwa "100 bidang" sebagian besar tidak relevan: pisahkan formulir Anda, karena bukan 100 elemen, ini beberapa bagian, masing-masing dengan sejumlah input, jadi terapkan desain yang baik dan buat setiap bagian komponennya sendiri, dengan pengelompokan komponen untuk formulir kelompok. Ini biasanya membuat komponen bertanggung jawab atas kurang dari 10 input, dan tiba-tiba arsitektur informasi Anda jauh lebih masuk akal. Formulir kirim, sebagai tindakan browser, tentu saja hanya melihat "formulir Anda" dan mengirimkan semuanya sekaligus. Desain UI yang bersih dan ditargetkan.
Mike 'Pomax' Kamermans
2
Terima kasih atas komentarnya. Namun saya perhatikan bahwa penautan negara telah usang pada React v15.
JoeTidee
3
@JasonChing maka Anda cukup membuat bug potensial ke dalam kode Anda. Bereaksi bukanlah "akan semua, mengakhiri semua" solusi untuk halaman web, itu adalah kerangka kerja untuk membangun antarmuka, dan itu bertanggung jawab untuk manajemen negara dan UI render yang sebenarnya sebagai renungan (pengguna Anda tidak berinteraksi dengan DOM, mereka berinteraksi dengan React. Pembaruan DOM hanyalah langkah terakhir yang tidak sinkron (tapi sangat cepat) sehingga UI secara visual mencerminkan keadaan). Jika Anda ingin mengabaikan itu, pertanyaan yang lebih penting adalah: mengapa Anda menggunakan Bereaksi? Karena tanda terbaik yang Anda gunakan salah adalah menggabungkan Bereaksi dan jQuery.
Mike 'Pomax' Kamermans
17

Berhasil mendapatkan nilai bidang input dengan melakukan sesuatu seperti ini:

import React, { Component } from 'react';

class App extends Component {

constructor(props){
super(props);

this.state = {
  username : ''
}

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


updateInput(event){
this.setState({username : event.target.value})
}


handleSubmit(){
console.log('Your input value is: ' + this.state.username)
//Send state to the server code
}



render(){
return (
    <div>
    <input type="text" onChange={this.updateInput}></input>
    <input type="submit" onClick={this.handleSubmit} ></input>
    </div>
  );
}
} 

//output
//Your input value is: x
Hugo Wesley
sumber
1
Mengapa menggunakan "setState"? Ini melibatkan rendering ulang..bukan?
Luca Davanzo
15

Dalam reaksi 16, saya menggunakan

<Input id="number" 
       type="time" 
       onChange={(evt) => { console.log(evt.target.value); }} />
Pyae Sone
sumber
tidak berfungsi jika bidang diisi secara otomatis berdasarkan beban usia
SeanMC
4

Saya berhasil melakukan ini dengan mengikat "ini" ke fungsi updateInputValue (evt) dengan

this.updateInputValue = this.updateInputValue.bind (ini);

Namun nilai input = {this.state.inputValue} ... ternyata bukan ide yang bagus.

Berikut kode lengkapnya di babel ES6:

class InputField extends React.Component{


  constructor(props){
   super(props);
   //this.state={inputfield: "no value"};   
   this.handleClick = this.handleClick.bind(this);
   this.updateInputValue = this.updateInputValue.bind(this);
  }

  handleClick(){
   console.log("trying to add picture url");
   console.log("value of input field : "+this.state.inputfield);

  }

  updateInputValue(evt){
    //console.log("input field updated with "+evt.target.value);
    this.state={inputfield: evt.target.value};   

  }

  render(){
    var r; 
    r=<div><input type="text" id="addpixinputfield" 
            onChange={this.updateInputValue} />
      <input type="button" value="add" id="addpix" onClick={this.handleClick}/>
      </div>;    
    return r;
   }
}
Matthias Liszt
sumber
2

kesalahan Anda adalah karena Anda menggunakan kelas dan ketika menggunakan kelas kami harus mengikat fungsi dengan ini agar berfungsi dengan baik. Lagi pula ada banyak tutorial mengapa kita harus "ini" dan apa yang "ini" lakukan di javascript.

jika Anda memperbaiki tombol kirim Anda itu harus berfungsi:

<button type="button" onClick={this.onSubmit.bind(this)} className="btn">Save</button>

dan juga jika Anda ingin menunjukkan nilai input itu di konsol Anda harus menggunakan var title = this.title.value;

Soroush Bk
sumber
2
tautan ini mungkin berguna jika Anda ingin tahu lebih banyak tentang "ini"
Soroush Bk
2

Berikan <input>id unik

<input id='title' ...>

dan kemudian menggunakan API Web standar untuk referensi di DOM

const title = document.getElementById('title').value

Tidak perlu terus memperbarui status Bereaksi dengan setiap penekanan tombol. Cukup dapatkan nilainya saat dibutuhkan.

Brent Washburne
sumber
1
// On the state
constructor() {
  this.state = {
   email: ''
 }
}

// Input view ( always check if property is available in state {this.state.email ? this.state.email : ''}

<Input 
  value={this.state.email ? this.state.email : ''} 
  onChange={event => this.setState({ email: event.target.value)}
  type="text" 
  name="emailAddress" 
  placeholder="[email protected]" />
Kidali Kevin
sumber
sementara jawaban Anda mungkin baik untuk pertanyaan, selalu lebih baik untuk menambahkan beberapa penjelasan. Harap luangkan 2 menit untuk menambahkannya. Ini akan meningkatkan jawaban Anda juga untuk pengguna di masa depan.
DaFois
tentu, saya akan melakukannya.
Kidali Kevin
0

Anda bisa mendapatkan nilai input tanpa menambahkan fungsi 'onChange'.

Cukup tambahkan ke elemen input a 'ref attr:

Dan kemudian gunakan this.refs untuk mendapatkan nilai input saat Anda membutuhkannya.

E1ad
sumber
3
Ini tidak direkomendasikan lagi.
JoeTidee
1
Anda dapat menggunakannya, tetapi disarankan untuk menjaga aliran data dalam satu arah menggunakan alat peraga dan panggilan balik.
JoeTidee
Akan lebih baik untuk menambahkan contoh menambahkan referensi dengan benar, Yaitu Menggunakan panggilan balik referensi bukan string warisan.
JoeTidee
0

Ubah ref Anda menjadi: ref='title'dan hapus name='title' Lalu hapus var title = this.titledan tulis:

console.log(this.refs.title.value)

Juga Anda harus menambahkan .bind(this)untukthis.onSubmit

(Ini bekerja dalam kasus saya yang sangat mirip, tetapi bukannya onClicksaya miliki onSubmit={...}dan itu diletakkan dalam bentuk ( <form onSubmit={...} ></form>))

Katarzyna Wrońska
sumber
0

jika Anda menggunakan komponen kelas maka hanya 3 langkah - pertama Anda harus menyatakan keadaan untuk input Anda yang diajukan misalnya this.state = {name: ''} . Kedua, Anda perlu menulis fungsi untuk mengatur keadaan ketika berubah di bawah ini contohnya setName () dan akhirnya Anda harus menulis input jsx misalnya <input value = {this.name} onChange = {this.setName} />

import React, { Component } from 'react'

export class InputComponents extends Component {
    constructor(props) {
        super(props)

        this.state = {
             name:'',
             agree:false
        }
        this.setName = this.setName.bind(this);
        this.setAgree=this.setAgree.bind(this);
    }

    setName(e){
        e.preventDefault();
        console.log(e.target.value);
        this.setState({
            name:e.target.value
        })
    }
    setAgree(){
        this.setState({
            agree: !this.state.agree
        }, function (){
            console.log(this.state.agree);
        })
    }
    render() {
        return (
            <div>
                <input type="checkbox" checked={this.state.agree} onChange={this.setAgree}></input>
                < input value={this.state.name} onChange = {this.setName}/>
            </div>
        )
    }
}

export default InputComponents
Tuan
sumber
0
export default class MyComponent extends React.Component {

onSubmit(e) {
    e.preventDefault();
    var title = this.title.value; //added .value
    console.log(title);
}

render(){
    return (
        ...
        <form className="form-horizontal">
            ...
            <input type="text" className="form-control" ref={input => this.title = input} name="title" />
            ...
        </form>
        ...
        <button type="button" onClick={this.onSubmit} className="btn">Save</button>
        ...
    );
}

};
Pranav Agarwal
sumber
0

menggunakan bidang yang tidak terkontrol:

export default class MyComponent extends React.Component {

    onSubmit(e) {
        e.preventDefault();
        console.log(e.target.neededField.value);
    }

    render(){
        return (
            ...
            <form onSubmit={this.onSubmit} className="form-horizontal">
                ...
                <input type="text" name="neededField" className="form-control" ref={(c) => this.title = c} name="title" />
                ...
            </form>
            ...
            <button type="button" className="btn">Save</button>
            ...
        );
    }

};
Georg
sumber