React.js: Bir onChange işleyicisiyle farklı girişleri tanımlama


142

Buna yaklaşmanın doğru yolunun ne olduğunu merak ediyorum:

var Hello = React.createClass({
getInitialState: function() {
    return {total: 0, input1:0, input2:0};
},
render: function() {
    return (
        <div>{this.state.total}<br/>
            <input type="text" value={this.state.input1} onChange={this.handleChange} />
            <input type="text" value={this.state.input2} onChange={this.handleChange} />
        </div>
    );
},
handleChange: function(e){
    this.setState({ ??? : e.target.value});
    t = this.state.input1 + this.state.input2;
    this.setState({total: t});
}
});

React.renderComponent(<Hello />, document.getElementById('content'));

Açıkçası, her farklı girişi işlemek için ayrı tutamak değiştirme işlevleri oluşturabilirsiniz, ancak bu çok hoş değil. Benzer şekilde, sadece bireysel bir giriş için bir bileşen oluşturabilirsiniz, ancak bunu böyle yapmanın bir yolu olup olmadığını görmek istedim.

Yanıtlar:


163

Gibi standart HTML niteliklerini uymanızı tavsiye nameüzerine inputcihazın girişleri tespit etmek Elements. Ayrıca, durumunuza başka değerler ekleyerek oluşturulabildiğinden "toplam" değerini ayrı bir değer olarak tutmanız gerekmez:

var Hello = React.createClass({
    getInitialState: function() {
        return {input1: 0, input2: 0};
    },
    render: function() {
        const total = this.state.input1 + this.state.input2;

        return (
            <div>{total}<br/>
                <input type="text" value={this.state.input1} name="input1" onChange={this.handleChange} />
                <input type="text" value={this.state.input2} name="input2" onChange={this.handleChange} />
            </div>
        );
    },
    handleChange: function(e) {
        this.setState({[e.target.name]: e.target.value});
    }
});

React.renderComponent(<Hello />, document.getElementById('content'));

3
Başlangıçta bunu yapmaya çalışıyordum, ancak setState ({e.target.name ... çalışmıyor) - bir sözdizimi hatası. Obj [e.target.name] ve setState ile geçici bir nesne yapmak zorundasınız. Bu tür işler, ancak durum nesnesi güncellemesinde bir tür gecikme var gibi görünüyor
T3db0t

1
"Gecikme tür" böylece açıklama görmezden requestAnimationFrame (ı varsayalım) sırasında setState güncelleme olduğunu
T3db0t

24
@ T3db0t Bu ES6 sözdizimi çalışır:this.setState({ [e.target.name]: e.target.value });
XåpplI'-I0llwlg'I -

2
Bağlamayı kullanmak daha iyi bir yaklaşımdır. OnChange işleyicisini div gibi bir name özelliği olmayan bir öğeye eklerseniz bu yaklaşım işe yaramaz.
ericgrosse

3
@ericgrosse bind, bu durumda pek çok gereksiz işlev oluşturduğunuz için daha iyi değildir. Ayrıca, gerekirse bir veri özniteliği ya da başka bir öğe üzerinde bir şey kullanabilirsiniz
aw04

106

Sen kullanabilirsiniz .bindparametreleri önceden inşa etmek yöntemi handleChangeyöntemiyle. Şöyle bir şey olurdu:

  var Hello = React.createClass({
    getInitialState: function() {
        return {input1:0, 
                input2:0};
    },
    render: function() {
      var total = this.state.input1 + this.state.input2;
      return (
        <div>{total}<br/>
          <input type="text" value={this.state.input1} 
                             onChange={this.handleChange.bind(this, 'input1')} />
          <input type="text" value={this.state.input2} 
                             onChange={this.handleChange.bind(this, 'input2')} />
        </div>
      );
    },
    handleChange: function (name, e) {
      var change = {};
      change[name] = e.target.value;
      this.setState(change);
    }
  });

  React.renderComponent(<Hello />, document.getElementById('content'));

( totalYapılması önerilen şey olduğu için render zamanında da hesaplandım.)


13
this.handleChange.bind(...)Yeni bir işlev oluşturan hızlı bir hatırlatma . İle veya benzeri bir şey kullanmanız shouldComponentUpdatehalinde PureRenderMixinkırılacaktır. Tek bir değer değiştiğinde tüm giriş bileşenleriniz yeniden gönderilecektir.
zemirco

5
Eğer uygulanmasını değiştirirseniz handleChangeiçin handleChange(name) { return event => this.setState({name: event.target.value}); }siz "aynı" fonksiyonu geçebilir (o kullanarak bitti gibi yeni işlev oluşturmaz .bind()Ardından, bu tür işlevi iletebilirsiniz:this.handleChange("input1")
Andreyco

1
SetState'in doğasının, birinin handChange işlevindeki geçerli durumu elde edemeyeceğini, ancak önceki durumu, this.state.input1'i kullanacağını belirtmenin de önemli olduğunu düşünüyorum. this.setState(change, function () { console.log(this.state.input1); );Referans gibi bir geri arama oluşturmak için uygun bir yaklaşım olacaktır : stackoverflow.com/questions/30782948/…
Charlie-Greenman

39

onChangeOlay kabarcıklar ... Böyle bir şey yapabiliriz Yani:

// A sample form
render () {
  <form onChange={setField}>
    <input name="input1" />
    <input name="input2" />
  </form>
}

Ve setField yönteminiz şu şekilde görünebilir (ES2015 veya daha yenisini kullandığınızı varsayarsak:

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

Birkaç uygulamada buna benzer bir şey kullanıyorum ve oldukça kullanışlı.


11

Kullanımdan kaldırılmış çözüm

valueLink/checkedLinkolan kaldırılan bazı kullanıcıların kafa karıştırıcı çünkü çekirdekten, yanıt verin. React'ın son bir sürümünü kullanırsanız bu yanıt çalışmaz. Ancak isterseniz, kendi Inputbileşeninizi oluşturarak kolayca taklit edebilirsiniz

Eski cevap içeriği:

Ulaşmak istediğiniz şey, React'in 2 yollu veri bağlama yardımcılarını kullanarak çok daha kolay bir şekilde elde edilebilir.

var Hello = React.createClass({
    mixins: [React.addons.LinkedStateMixin],
    getInitialState: function() {
        return {input1: 0, input2: 0};
    },

    render: function() {
        var total = this.state.input1 + this.state.input2;
        return (
            <div>{total}<br/>
                <input type="text" valueLink={this.linkState('input1')} />;
                <input type="text" valueLink={this.linkState('input2')} />;
            </div>
        );
    }

});

React.renderComponent(<Hello />, document.getElementById('content'));

Kolay değil mi?

http://facebook.github.io/react/docs/two-way-binding-helpers.html

Kendi karışımınızı bile uygulayabilirsiniz


Durumu ayarlamak için neden bir değiş tokuş yapmalıyız? Daha sonra ReactJS!
Junaid Qadir

Bu çözümün kullanımdan kaldırıldığını unutmayın
Philipp

6

Bunu şu şekilde de yapabilirsiniz:

...
constructor() {
    super();
    this.state = { input1: 0, input2: 0 };
    this.handleChange = this.handleChange.bind(this);
}

handleChange(input, value) {
    this.setState({
        [input]: value
    })
}

render() {
    const total = this.state.input1 + this.state.input2;
    return (
        <div>
            {total}<br />
            <input type="text" onChange={e => this.handleChange('input1', e.target.value)} />
            <input type="text" onChange={e => this.handleChange('input2', e.target.value)} />
        </div>
    )
}

benim için çalışmadı. React geliştirici araçlarını gördüm. input1 / input2 yerine değişken / nesneye değerler yaratma ve atama
Gaurravs

1
@Gaurravs evet haklısın. Ben eklemek için gerekli []etrafında inputsetstate içine. Bu özellik dinamik olarak atanır
inostia

4

Adlı özel bir Reactözniteliği kullanabilir refve ardından ' işlevini onChangekullanarak etkinlikteki gerçek DOM düğümlerini eşleştirebilirsiniz :ReactgetDOMNode()

handleClick: function(event) {
  if (event.target === this.refs.prev.getDOMNode()) {
    ...
  }
}

render: function() {
  ...
  <button ref="prev" onClick={this.handleClick}>Previous question</button>
  <button ref="next" onClick={this.handleClick}>Next question</button>
  ...
}

En azından 0.13'te this.refs'in bir pref özelliği yoktur.
blub

2
@usagidon - prevsadece render()yöntemde belirlediğim bir isim
Janusz Kacalak

2
React v0.14'ten itibaren yapabilirsiniz event.target === this.refs.prev. facebook.github.io/react/blog/2015/10/07/…
XåpplI'-I0llwlg'I -

0

@ErkekTerimleri

Çok alanlı formlar söz konusu olduğunda, React'in temel özelliği olan bileşenleri kullanmak mantıklıdır.

Projelerimde, minimum değer pervanesi alan TextField bileşenleri oluşturuyorum ve bir girdi metin alanının ortak davranışlarını ele almayı sağlıyor. Bu şekilde, değer durumunu güncellerken alan adlarını takip etme konusunda endişelenmenize gerek kalmaz.

[...]

handleChange: function(event) {
  this.setState({value: event.target.value});
},
render: function() {
  var value = this.state.value;
  return <input type="text" value={value} onChange={this.handleChange} />;
}

[...]

0

Tek bir çocuğun değerini yöneten inputayrı bir InputFieldbileşen oluşturarak her bir çocuğun değerini izleyebilirsiniz input. Örneğin şunlar InputFieldolabilir:

var InputField = React.createClass({
  getInitialState: function () {
    return({text: this.props.text})
  },
  onChangeHandler: function (event) {
     this.setState({text: event.target.value})
  }, 
  render: function () {
    return (<input onChange={this.onChangeHandler} value={this.state.text} />)
  }
})

Artık her bir alt öğeyi izlemek için ebeveynin durumunda ayrı değerler oluşturmadan her birinin değeri inputbu InputFieldbileşenin ayrı bir örneği içinde izlenebilir .


0

Soruna gerçekten basit bir çözüm sunacağım. İki girişimiz olduğunu varsayalım usernamevepassword , ama biz yeniden kullanmak ve yazma Demirbaş kodu yok böylece bizim sapı, kolay ve jenerik olmak istiyorum.

I. formumuz:

                <form>
                    <input type="text" name = "username" onChange={this.onChange} value={this.state.username}/>
                    <input type="text" name = "password" onChange={this.onChange} value={this.state.password}/>
                    <br></br>
                    <button type="submit">Submit</button>
                </form>

II.Kurulumuzu yapmak istediğimiz kurucumuz usernameve passwordonlara kolayca erişebilmemiz için:

constructor(props) {
    super(props);
    this.state = {
        username: '',
        password: ''
    };

    this.onSubmit = this.onSubmit.bind(this);
    this.onChange = this.onChange.bind(this);
}

III.Tek bir onChangeolayla ilginç ve "genel" tanıtıcı buna dayanır:

onChange(event) {
    let inputName = event.target.name;
    let value = event.target.value;

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


    event.preventDefault();
}

Açıklamama izin ver:

Bir değişiklik tespit edildiğinde 1.When onChange(event)denir

2. sonra alanın isim parametresini ve değerini alırız:

let inputName = event.target.name; ex: username

let value = event.target.value; ex: itsgosho

3. name parametresine dayanarak, değerimizi yapıcıdaki durumdan alır ve değerle güncelleriz:

this.state['username'] = 'itsgosho'

Burada dikkat edilmesi gereken nokta, alan adının durumdaki parametrenizle eşleşmesi gerektiğidir

Umarım birine bir şekilde yardım ettim :)


0

Durumunuzun anahtarı giriş alanınızın adıyla aynı olmalıdır. Sonra bunu handleEvent yönteminde yapabilirsiniz;

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

-1

Merhaba ssorallen cevabını geliştirdik . Fonksiyonu bağlamanız gerekmez, çünkü girişe onsuz erişebilirsiniz.

var Hello = React.createClass({
    render: function() {
        var total = this.state.input1 + this.state.input2;
        return (
             <div>{total}<br/>
                  <input type="text" 
                    value={this.state.input1}
                    id="input1"  
                    onChange={this.handleChange} />
                 <input type="text" 
                    value={this.state.input2}
                    id="input2" 
                    onChange={this.handleChange} />
            </div>
       );
   },
   handleChange: function (name, value) {
       var change = {};
       change[name] = value;
       this.setState(change);
   }
});

React.renderComponent(<Hello />, document.getElementById('content'));
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.