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
Search
bileşende bulunur. - Durum şu şekilde açıklanmaktadır:
{ görünür: boole, dosyalar: dizi, filtrelenmiş: dizi, sorgu: dize, şu andaSelectedIndex: tamsayı }
files
dosya yolları içeren potansiyel olarak çok büyük bir dizidir (10000 giriş makul bir sayıdır).filtered
kullanı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, ancakcurrentlySelectedIndex
bu, filtrelenmiş listeden seçili öğenin dizinidir.Kullanıcı
Input
bileşene 2'den fazla harf yazarsa, dizi filtrelenir ve filtrelenmiş dizideki her giriş için birResult
bileşen oluşturulurHer
Result
bileş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ı,
Input
bileşene odaklanırken yukarı veya aşağı tuşlarına basarsa ,currentlySelectedIndex
değişikliklerfiltered
diziye 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 files
React'in geliştirme sürümünü kullanarak yeterince küçük bir dizi ile test ettim ve hepsi iyi çalıştı.
files
10000 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 Result
değildim ve listeyi yalnızca Search
bileş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 currentlySelectedIndex
değiştiğinde, yeniden oluşturmaya neden olur ve liste her seferinde yeniden oluşturulur. key
Her bir li
elemente bir değer koyduğum için, React'in değişikliğe uğramamış her diğer li
elementi 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.