ReactJS kullanarak bir giriş alanının değerini nasıl alabilirim?


190

Aşağıdaki React bileşenim var:

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 bana veriyor undefined- bu kodda yanlış olan herhangi bir fikir var mı?


7
this.onSubmit.bind(this);
zerkms

Nice - Cevap olarak eklemek istiyorum ve onu işaretleyeceğim (?)
JoeTidee

2
e.target.valuebağlamadan ne haber ?
omarjmh

1
e.target.value giriş alanını değil düğmeyi hedeflemez mi?
JoeTidee

onSubmitYöntemi tıklatıldığında gönder düğmesine (DOM öğesi) bağlamanız gerekir (örn. onClick={this.onSubmit.bind(this)}). Ve formdaki başlık girişinin değerine erişmek isterseniz kullanabilirsiniz onSubmit(event) { const title = event.target.elements.title.value; }.
tfmontague

Yanıtlar:


11

MyComponent extends React.Component sınıfı altında yapıcı kullanmalısınız

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

Sonra unvanın sonucunu alacaksınız


317

Burada çalıştığınız (çalışmak zorunda olduğunuz) React sürümüne ve kanca kullanmak isteyip istemediğinize bağlı olarak üç cevap vardır.

Her şey sırayla:

O mi: düzgün (PROTIP şeyler yapabilirsiniz, böylece eserler Tepki nasıl anlamak önemlidir süper . Nasıl yapılacağını aslında açıklıyor bir şekilde web sitesi tepki üzerine öğretici egzersiz Tepki aracılığıyla İyi yazıldığı değerinde çalışan ve kapaklar tüm temelleri bir şeyler). "Düzgün" burada bir tarayıcıda görüntülenen bir uygulama arayüzü yazdığınız anlamına gelir; tüm arayüz çalışmaları "web sayfası yazıyorsanız alışık olduğunuz şeylerde" değil React'te gerçekleşir (bu nedenle React uygulamaları "web sayfaları" değil "uygulamalar" dır).

Reaksiyon uygulamaları iki şeyden oluşur:

  1. bileşenin, hangi üst öğenin bu bileşenin üst öğesi tüm yaşam döngüsü boyunca değiştirebileceği bir örneğini oluşturduğunu bildirdiği şekilde ve
  2. bileşenin kendi yaşam döngüsü boyunca kendisini değiştirebileceği kendi iç durumu.

Eğer açıkça ne konum değil bir kullanmak tepki söylediğimde: Eğer kullananlara ardından HTML elemanlarını üreten ve tepki kullandığınızda yapıyor <input>, örneğin, sen edilir değil bir HTML giriş elemanı oluştururken, sen anlatıyorsun bir giriş nesne Tepki yaratmak için React o olur hale kimin olay işleme görünüyor az bir HTML giriş öğesinin ve gibi ama tarafından kontrol edilmeyen HTML elementin giriş olayları.

React kullanırken, yaptığınız şey kullanıcıya (genellikle işlenebilir) veriler sunan, kullanıcı etkileşiminin Bileşenin durumunu değiştirdiği ve uygulama arayüzünüzün bir bölümünün yeni durumu yansıtmasına neden olabilecek uygulama kullanıcı arabirimi öğeleri oluşturmaktır . Bu modelde, durum her zaman nihai otoritedir, web'de tarayıcının DOM'su olan "oluşturmak için kullanılan kullanıcı arayüzü kitaplığı" değil. DOM, bu programlama modelinde neredeyse sonradan düşünülen bir şeydir: React'in kullandığı özel UI çerçevesi.

Dolayısıyla, bir giriş elemanı durumunda, mantık:

  1. Giriş öğesini yazıyorsunuz,
  2. giriş öğenize henüz hiçbir şey olmuyor, olay React tarafından durduruldu ve hemen öldürüldü ,
  3. Reaksiyon, olayı olay işleme için ayarladığınız işleve iletir,
  4. O işlevi olabilir , bir devlet güncelleştirme planlamak
  5. öyleyse, React bu durum güncellemesini (eşzamansız olarak!) çalıştırır ve rendergüncellemeden sonra bir çağrıyı tetikler , ancak yalnızca durum güncellemesi durumu değiştirdiğinde .
  6. Yalnızca sonra bu yerini almıştır işlemek siz "bir mektup yazdınız" diye UI gösterisi olacak.

O kadar Bunların hepsi, az değilse, milisaniyeler içinde olur bakar size "sadece bir sayfada bir giriş elemanı kullanılarak" dan alıştığınız aynı şekilde giriş öğesinin yazdığınız gibi, ama bu kesinlikle değil ne var olmuş.

Bununla birlikte, React'teki öğelerden nasıl değer elde edileceğine dair:

ES5 ile 15 ve altı reaksiyonlar

İşleri düzgün bir şekilde yapmak için, bileşeninizin bir giriş alanı aracılığıyla gösterilen bir durum değeri vardır ve UI öğesinin değişiklik olaylarını tekrar bileşene göndermesini sağlayarak bunu güncelleyebiliriz:

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

Kullandığımız Tepkisiz tell Yani updateInputValuekullanıcı etkileşimini işlemek için işlevini kullanın setStatedevlet güncellemesini ve gerçeğini planlamak için bu renderiçine musluklar this.state.inputValueo devlet güncellemeden sonra rerenders zaman, kullanıcı, yazdıklarına dayalı güncelleme metni göreceği yollarla.

yorumlara göre zeyilname

Kullanıcı arabirimi girişlerinin durum değerlerini temsil ettiği göz önüne alındığında (kullanıcı sekmesini yarıda kapatırsa ve sekme geri yüklenirse ne olduğunu düşünün. Doldurdukları tüm değerlerin geri yüklenmesi gerekir mi? Öyleyse, bu durum). Bu, büyük bir formun onlarca hatta yüz giriş formuna ihtiyaç duyduğunu hissettirebilir, ancak React, kullanıcı arayüzünüzü sürdürülebilir bir şekilde modellemekle ilgilidir: 100 bağımsız giriş alanınız yok, ilgili giriş gruplarınız var, böylece her birini sonra bir grup koleksiyonu olarak "ana" formunuzu oluşturun.

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

Bunun bakımı, dev bir tek form bileşeninden çok daha kolaydır. Grupları, her bir bileşenin aynı anda yalnızca birkaç giriş alanının izlenmesinden sorumlu olduğu durum bakımı olan Bileşenler'e bölün.

Ayrıca, tüm bu kodu yazmak için bir güçlük gibi hissedebilirsiniz, ancak bu yanlış bir tasarruftur: gelecekteki siz de dahil olmak üzere, geliştiriciler-kim-olmayanlar, aslında tüm bu girdilerin açıkça bağlandığını görmekten büyük ölçüde faydalanırlar, çünkü kod yollarının izlenmesini kolaylaştırır. Ancak, her zaman optimize edebilirsiniz. Örneğin, bir durum bağlayıcısı yazabilirsiniz

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']}/>
    });
  }
});

Tabii ki, bunun geliştirilmiş sürümleri var, bu yüzden https://npmjs.com adresine basın ve en sevdiğiniz React state bağlantı çözümünü arayın. Açık Kaynak çoğunlukla başkalarının zaten yaptıklarını bulmak ve bunu her şeyi sıfırdan yazmak yerine kullanmakla ilgilidir.

Reaksiyon 16 (ve 15.5 geçiş) ve 'modern' JS

React 16'dan (ve 15.5 ile yumuşak başlangıç) itibaren createClassçağrı artık desteklenmiyor ve sınıf sözdiziminin kullanılması gerekiyor. Bu iki şeyi değiştirir: bariz sınıf sözdizimi, ama aynı zamanda "ücretsiz" yapabilen thisbağlam bağlama createClass, bu yüzden işlerin hala işe yaramasını sağlamak için this, onWhateverişleyicilerin anonim işlevlerini korumak için bağlam gibi "şişman ok" gösterimini kullandığınızdan emin olun . onChangeburada kodunda biz kullanım:

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

Ayrıca, kişilerin bindtüm etkinlik işleme işlevleri için kurucularında kullandıklarını görmüş olabilirsiniz , örneğin:

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

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

Bunu yapma.

Neredeyse her kullandığınızda bind, meşhur "yanlış yapıyorsunuz" geçerlidir. Sınıfınız zaten nesne prototipini ve dolayısıyla örnek bağlamını zaten tanımlar. Üstüne koymayın bind; yapıcıdaki tüm işlev çağrılarınızı çoğaltmak yerine normal olay yönlendirme kullanın, çünkü bu çoğaltma hata yüzeyinizi arttırır ve sorun kodunuzu çağırmak yerine kurucunuzda olabileceğinden hataları izlemeyi çok daha zorlaştırır. Çalışmak zorunda olduğunuz (veya seçtiğiniz) başkalarına bakım yükü koymanın yanı sıra.

Evet, tepki belgelerinin iyi olduğunu biliyorum. Değil, yapma.

Reaksiyon 16.8, kancalarla fonksiyon bileşenlerini kullanma

React 16.8'den itibaren fonksiyon bileşeni (yani kelimenin tam anlamıyla sadece propsargüman olarak alan bir fonksiyon, hiç bir sınıf yazmadan sanki bir bileşen sınıfının bir örneği gibi kullanılabilir), kancalar kullanılarak durum verilebilir .

Tam sınıf koduna ihtiyacınız yoksa ve tek bir örnek işlevi yapacaksa, şimdi useStatetek bir durum değişkeni almak için kancayı ve yukarıdaki örneklerle kabaca aynı olmayan güncelleme işlevini elde etmek için kullanabilirsiniz. setStateişlev çağrısı:

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

Daha önce sınıflar ve fonksiyon bileşenleri arasındaki gayri resmi ayrım "fonksiyon bileşenlerinin durumu yok" idi, bu yüzden artık arkasına saklanamıyoruz: Fonksiyon bileşenleri ve sınıf bileşenleri arasındaki fark çok iyi bir şekilde birkaç sayfaya yayılmış olarak bulunabilir ne yaptığınızı bilmek ve böylece kendinizi programlamak için en iyi (sizin için ne anlama geliyorsa) çözümü seçip seçmediğinizi bilmeniz için okumanız gereken yazılı tepki belgeleri (sizin için uygun şekilde yanlış yorumlamak için bir satır açıklaması yok!) bir problemin dışında.


4
Çok fazla devlet kullanmanın kötü bir fikir olduğunu söyleyen birkaç çevrimiçi makale okudum. Başvurumun belirli bir formunda yaklaşık 100 form alanım var. Devleti kurtarmak için bir işlev tanımlamak, işleri yapmak için gereksiz derecede zorlu bir yol gibi geliyor. Eğer onClick = {this.onSubmit.bind (this)} kullanabilirsiniz, bu değeri almak için iyi bir yol gibi görünüyor (daha sonra isterseniz, bileşen durumunu ayarlamak) - Bu konuda bazı yorumlar takdir ediyorum.
JoeTidee

5
bu yüzden daha akıllı kod yazın. form girişleri kesinlikle durumdur (bir kullanıcı sekmesini yarıda kapatırsa ve sekme geri yüklenirse ne olduğunu düşünün. Doldurdukları tüm bu değerler geri yüklenmeli mi? evet? durum ), bu yüzden biraz durum bakım kodu yazın. Facebook'un da yüzlerce form değeri vardır ve onların çılgınlığına çözümleri React'ti. Gerçekten iyi çalışıyor . Durumunuzu kullanırken kodunuzu biraz daha kolay hale getirmenin bir yolu , yine React sitesinde açıklanan iki yönlü durum bağlantısını kullanmaktır . Okumaya değer! =)
Mike 'Pomax' Kamermans

2
Ayrıca, "100 alanın" çoğunlukla alakasız olduğunu unutmayın: formunuzu ayırın, çünkü 100 öğe olmadığından, her biri bir dizi girişe sahip birkaç bölümdür, bu yüzden iyi bir tasarım uygulayın ve her bölümü form için gruplama bileşenleri ile kendi bileşeni yapın grupları. Bu genellikle bir bileşeni 10'dan daha az girişten sorumlu hale getirir ve aniden bilgi mimariniz çok daha mantıklıdır. Form gönderimi, bir tarayıcı eylemi olarak, elbette "formunuzu" görür ve her şeyi tek seferde sunar. Temiz, hedeflenmiş kullanıcı arayüzü tasarımı.
Mike 'Pomax' Kamermans

2
Yorumlar için teşekkürler. Ancak React v15 itibariyle durum bağlantısının kullanımdan kaldırıldığını fark ettim.
JoeTidee

3
@ JasonChing, kodunuza potansiyel hatalar oluşturdunuz. Bir web sayfalarına çözüm "bütün, her şey bitecek olması" değil Tepki, bu arayüzler oluşturmak için bir çerçeve, ve o senin kullanıcılar ile etkileşim, DOM ile değil etkileşim yapmak (sonradan devlet yönetimi ve fiili UI render sorumludur Tepki: DOM güncellemeleri basitçe asenkron (ancak inanılmaz derecede hızlı) bir son adımdır, böylece kullanıcı arayüzü durumu görsel olarak yansıtır). Bunu atlamak istiyorsanız, daha önemli soru şudur: React'i neden kullanıyorsunuz? Çünkü yanlış kullandığınız en iyi işaret React ve jQuery'yi birleştirmektir.
Mike 'Pomax' Kamermans

17

Aşağıdaki gibi bir şey yaparak giriş alanı değerini almayı başardı:

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

1
Neden "setState" kullanıyorsunuz? Bu bir yeniden oluşturma içerir ... değil mi?
Luca Davanzo

15

Tepki 16'da kullanıyorum

<Input id="number" 
       type="time" 
       onChange={(evt) => { console.log(evt.target.value); }} />

alan yaş yükünde otomatik olarak doldurulursa
çalışmaz

4

Ben updateInputValue (evt) işlevine "bu" bağlayarak bunu başardı

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

Ancak giriş değeri = {this.state.inputValue} ... iyi bir fikir değildi.

İşte babil ES6'daki tam kod:

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

2

hatanız, sınıf kullanmanızdan kaynaklanır ve sınıfı kullanırken, iyi çalışması için fonksiyonları Bu ile bağlamamız gerekir. Neyse "neden" ve "bu" ne javascript yapmak ne öğretici bir sürü vardır.

gönder düğmenizi düzeltirseniz, işe yaraması gerekir:

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

ayrıca bu girişin değerini konsolda göstermek istiyorsanız var title = this.title.value;


2
"this" hakkında daha fazla bilgi edinmek istiyorsanız bu link size yardımcı olabilir
Soroush Bk


2

<input>Benzersiz bir kimlik verin

<input id='title' ...>

ve DOM'da referans vermek için standart Web API'sini kullanın

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

Tepki durumunu sürekli olarak her tuşa basarak güncellemeye gerek yoktur. Gerektiğinde değeri elde edin.


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="johdoe@somewhere.com" />

cevabınız soru için iyi olsa da, biraz açıklama eklemek her zaman daha iyidir. Lütfen eklemek için 2 dakikanızı ayırın. Bu, gelecekteki kullanıcılar için de yanıtınızı geliştirecektir.
DaFois

emin, bunu yapacağım.
Kidali Kevin

0

'OnChange' işlevi eklemeden bir giriş değeri alabilirsiniz.

Sadece bir 'ref attr giriş öğesine ekleyin:

Ve sonra this.refs komutunu kullanarak ihtiyacınız olduğunda girdi değerini alabilirsiniz.


3
Bu artık önerilmez.
JoeTidee

1
Bunları kullanabilirsiniz, ancak sahne ve geri çağrıları kullanarak veri akışını bir yönde tutmanız önerilir.
JoeTidee

Ref'lerin doğru bir şekilde eklenmesi, örneğin eski bir dize yerine bir ref geri çağrısı kullanılması örneği eklemek iyi olur.
JoeTidee

0

Başvurunuzu şununla değiştirin: ref='title've silin name='title' Sonra silin var title = this.titleve yazın:

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

Ayrıca eklemeniz .bind(this)gerekirthis.onSubmit

(Benim durumumda oldukça benzerdi, ama yerine onClickvardı onSubmit={...}ve formda ( <form onSubmit={...} ></form>))


0

Eğer sınıf bileşenini kullanırsanız, sadece 3 adım - önce bu girişin durumunu bildirmeniz gerekir, örneğin this.state = {name: ''} . İkinci olarak, feryat örneğinde değiştiğinde durumu ayarlamak için bir işlev yazmanız gerekir, setName () ve son olarak, örneğin <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

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

};

0

kontrolsüz alanlar kullanarak:

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

};
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.