2016-03-21 82 views
0

İstenmeyen sayıda alt bileşenin kaydını tutmaya çalışıyorum.Tepki: dinamik bileşen refs oluşturma ve başvuru referansı

Normalde this.refs.refName öğesine başvuruda bulunursunuz, ancak benim durumumda izlemeye devam etmem gereken keyfi bir miktar referansım var.

var NamesList = React.createClass({ 
    getAllNames: function() { 
    // Somehow return an array of names... 

    var names = []; 
    this.refs.????.forEach(function (span) { 
     names.push(span.textContent); 
    }) 
    }, 

    render: function() { 
    var names = ['jack','fred','bob','carl']; 
    var spans = []; 

    names.forEach(function (name) { 
     spans.push(<span contentEditable={true} ref='?????'>name</span>); 
    }); 

    return (
     <div> 
     {spans} 
     </div>; 
    ); 
    } 
}); 

ReactDOM.render(<NamesList></NamesList>, mountNode); 

Sorunu yaklaşıyorum Eğer yanlış bana bildirin:

İşte özlü bir örnek. İstenilen sonuç, bir RESTful hizmetinden bir Reaktif bileşenine veri aktarmak, kullanıcının bu verileri düzenlemesine izin vermek ve gerektiğinde tekrar dışa aktarmaktır. React refs dokümanlarında buna bir cevap bulamadım.

cevap

1

aşağıdaki bir dizi içinde her bir açıklığa ref tutan her bir yayılma addSpanRef yöntemiyle ref diziye ekleyebilmektedir için bu çalışır this.spans

adı.

getAllNames başvurulan tüm kapsamlardan geçer ve textContent öğelerini alır.

Alt bileşenleriniz varsa (bunun yerine), bu düğümlerde yöntemleri arayabilirsiniz!

var NamesList = React.createClass({ 

    // returns an array of names 
    getAllNames() { 
    return this.spans.map((span) => span.textContent); 
    }, 

    // Add to our spans refs array 
    addSpanRef (node) { 
    this.spans = [...this.spans, node]; 
    }, 

    render: function() { 
    this.spans = []; // create the spans refs array 
    var names = ['jack','fred','bob','carl']; 

    // Save a ref to "this" for the forEach loop 
    var thisRef = this; 
    names.forEach(function (name) { 
     spans.push(<span contentEditable={true} ref={thisRef.addSpanRef}>name</span>); 
    }); 

    return (
     <div> 
     {spans} 
     </div>; 
    ); 
    } 
}); 

ReactDOM.render(<NamesList></NamesList>, mountNode); 
1

1. Hızlı ve Kirli Çözüm: childNode yayılan üzerine textContent kabın üzerine bir ref koymak ve okumak için konteyner bileşeni üzerinde bütün isimleri okumak için

Tek yön ref yoluyla isimleri olduğunu okuyun.

componentDidMount: function() { 
    var elem = this.refs.container.getDOMNode(); 
    var nameNodes = elem.children; 
    var names = []; 
    for (var i=0; i<nameNodes.length; i++) { 
     names.push(nameNodes[i].textContent); 
    } 
    console.log(names); 
    }, 

Working codepen of this here.

Uyarı: Yukarıdaki kod kirli: kullanıcı, DOM değişimini bilmeden tepki süresinin içeriğini değiştirebilir. Ve bu (çok) kötü bir fikir.

2. Temizlik Çözeltisi Yani devlete ihtiyacımız olacak: Kullanıcı aralıkların içeriğini değiştirmek ve bunu bilmek ihtiyaçlarını tepki verebilir.
Ayrıca, tüm (yeni) düzenlenmiş adların bir dizisine ihtiyacınız olduğu için, bu durumun kapsayıcı düzeyinde bulunması gerekir.
İşte, her seferinde bir ad değiştiğinde üstlerinde bir yöntem çağıran, <EditableSpan> bileşenleriyle birlikte bir çözüm.

var EditableSpan = React.createClass({ onChange: function() { var newContent = event.target.textContent; this.props.onChange(this.props.index, newContent); }, render: function() { return <span contentEditable={true} onInput={this.onChange}> {this.props.name}</span> } }); 

onlar gerekli değildir, çünkü bu daha temiz bir çözüm artık sayılı referanslara kullandığını unutmayın: tüm veriler reaksiyona girdiği bilinmektedir, bu nedenle DOM okumak için ref gerekmez tepki. Bunun yerine, konteyner durumunu güncellemek için her değişiklikte event.target'u okur.

full working codepen Burada bulabilirsiniz.

Uyarı: Bu çözüm için hızlı ve kirli keys (isimleri) ekledim. React benzersiz olan (ve endeksi değil) tuşlara ihtiyaç duyar. Listedeki isimlerin benzersiz olmaları garanti edilmediğinden, bunun için daha akıllı bir çözüme ihtiyaç duyabilirsiniz (Kimlikler veya yaratılan zaman damgaları).

+0

Üzgünüm, açıklıkların _out_ adlarını dinamik olarak çekmeye çalışıyorum. Yaptığınız değişikliklerin dinamik olarak _setting_ ile ilgili olduğu anlaşılıyor. Sözde kodda: her bir span için textContent'i alın ve bunları bir dizi olarak döndürün. Ne istediğimi açıklamaya yardımcı olur mu? – joshuakcockrell

+0

Yanıtı 2 çözümle güncellendi. Lütfen ikinci çözümün, yayının textContent ile bir dizi döndürür, ancak refs kullanmadan olduğunu unutmayın. Tepki textContent'in tek sahibi ve yöneticisi olmalıdır. Yani isimleri almak için refs kullanmak için gerekli (ve buggy/yönetilemez kod kaynağı) gerekli değildir. – wintvelt