React ile filtrelenebilir bir liste oluşturma sürecindeyim. Listenin yapısı aşağıdaki resimde gösterildiği gibidir.
ÖNCÜL
İşte nasıl çalışması gerektiğine dair bir açıklama:
- Devlet, en üst düzey bileşen olan
Searchbileşende bulunur. - Durum şu şekilde açıklanmaktadır:
{
görünür: boole,
dosyalar: dizi,
filtrelenmiş: dizi,
sorgu: dize,
şu andaSelectedIndex: tamsayı
}
filesdosya yolları içeren potansiyel olarak çok büyük bir dizidir (10000 giriş makul bir sayıdır).filteredkullanıcı en az 2 karakter yazdıktan sonra filtrelenen dizidir. Türev verilerinin olduğunu biliyorum ve bu nedenle, eyalette saklamakla ilgili bir argüman yapılabilir, ancakcurrentlySelectedIndexbu, filtrelenmiş listeden seçili öğenin dizinidir.Kullanıcı
Inputbileşene 2'den fazla harf yazarsa, dizi filtrelenir ve filtrelenmiş dizideki her giriş için birResultbileşen oluşturulurHer
Resultbileşen, sorguyla kısmen eşleşen tam yolu görüntüler ve yolun kısmi eşleşme kısmı vurgulanır. Örneğin, bir Sonuç bileşeninin DOM'si, kullanıcı 'le' yazmış olsaydı, şöyle bir şey olurdu:<li>this/is/a/fi<strong>le</strong>/path</li>- Kullanıcı,
Inputbileşene odaklanırken yukarı veya aşağı tuşlarına basarsa ,currentlySelectedIndexdeğişikliklerfiltereddiziye göre değişir . BuResult, dizinle eşleşen bileşenin yeniden oluşturmaya neden olacak şekilde seçili olarak işaretlenmesine neden olur
SORUN
Başlangıçta bunu filesReact'in geliştirme sürümünü kullanarak yeterince küçük bir dizi ile test ettim ve hepsi iyi çalıştı.
files10000 giriş kadar büyük bir diziyle uğraşmak zorunda kaldığımda sorun ortaya çıktı . Giriş'e 2 harf yazmak büyük bir liste oluşturur ve gezinmek için yukarı ve aşağı tuşlarına bastığımda çok gecikmeli olurdu.
İlk başta elemanlar için tanımlı bir bileşene sahip Resultdeğildim ve listeyi yalnızca Searchbileşenin her renderında anında yapıyordum, şöyle ki:
results = this.state.filtered.map(function(file, index) {
var start, end, matchIndex, match = this.state.query;
matchIndex = file.indexOf(match);
start = file.slice(0, matchIndex);
end = file.slice(matchIndex + match.length);
return (
<li onClick={this.handleListClick}
data-path={file}
className={(index === this.state.currentlySelected) ? "valid selected" : "valid"}
key={file} >
{start}
<span className="marked">{match}</span>
{end}
</li>
);
}.bind(this));
Anlayabileceğiniz gibi, her currentlySelectedIndexdeğiştiğinde, yeniden oluşturmaya neden olur ve liste her seferinde yeniden oluşturulur. keyHer bir lielemente bir değer koyduğum için, React'in değişikliğe uğramamış her diğer lielementi yeniden oluşturmaktan kaçınacağını düşündüm className, ama görünüşe göre öyle değildi.
ResultÖğeler için bir sınıf tanımlamayı bitirdim, burada her Resultöğenin daha önce seçilip seçilmediğine ve mevcut kullanıcı girdisine göre yeniden oluşturulup oluşturulmayacağını açıkça kontrol ediyor :
var ResultItem = React.createClass({
shouldComponentUpdate : function(nextProps) {
if (nextProps.match !== this.props.match) {
return true;
} else {
return (nextProps.selected !== this.props.selected);
}
},
render : function() {
return (
<li onClick={this.props.handleListClick}
data-path={this.props.file}
className={
(this.props.selected) ? "valid selected" : "valid"
}
key={this.props.file} >
{this.props.children}
</li>
);
}
});
Liste artık şu şekilde oluşturulmuştur:
results = this.state.filtered.map(function(file, index) {
var start, end, matchIndex, match = this.state.query, selected;
matchIndex = file.indexOf(match);
start = file.slice(0, matchIndex);
end = file.slice(matchIndex + match.length);
selected = (index === this.state.currentlySelected) ? true : false
return (
<ResultItem handleClick={this.handleListClick}
data-path={file}
selected={selected}
key={file}
match={match} >
{start}
<span className="marked">{match}</span>
{end}
</ResultItem>
);
}.bind(this));
}
Bu, performansı biraz daha iyi hale getirdi , ancak yine de yeterince iyi değil. React'in üretim versiyonunu test ettiğimde işler sorunsuz çalıştı, hiç gecikme olmadı.
SONUÇ OLARAK
React'in geliştirme ve üretim sürümleri arasında bu kadar belirgin bir tutarsızlık normal mi?
React'in listeyi nasıl yönettiğini düşündüğümde anlıyor muyum / yanlış bir şey yapıyor muyum?
GÜNCELLEME 14-11-2016
Michael Jackson'ın buna çok benzer bir sorunu ele aldığı bu sunumunu buldum: https://youtu.be/7S8v8jfLb1Q?t=26m2s
Çözüm, AskarovBeknar'ın aşağıdaki cevabının önerdiği çözümle çok benzer.
GÜNCELLEME 14-4-2018
Bu görünüşe göre popüler bir soru olduğundan ve asıl soru sorulduğundan beri işler ilerlediğinden, sanal bir düzeni kavramak için yukarıda bağlantısı verilen videoyu izlemenizi öneririm, ayrıca sizi React Virtualized'i kullanmanızı tavsiye ederim tekerleği yeniden icat etmek istemiyorsanız kitaplık.



