मैं रिएक्ट के साथ एक फिल्टर करने योग्य सूची को लागू करने की प्रक्रिया में हूं। सूची की संरचना नीचे दी गई छवि में दिखाई गई है।
आधार
यहां बताया गया है कि यह कैसे काम करने वाला है:
- राज्य उच्चतम स्तर के घटक, घटक में रहता है
Search
। - राज्य का वर्णन इस प्रकार है:
{ दृश्यमान: बूलियन, फ़ाइलें: सरणी, फ़िल्टर्ड: सरणी, क्वेरी स्ट्रिंग, वर्तमान में चयनितइंडेक्स: पूर्णांक }
files
एक संभावित रूप से बहुत बड़ा है, फ़ाइल पथ वाले सरणी (10000 प्रविष्टियां एक प्रशंसनीय संख्या है)।filtered
उपयोगकर्ता द्वारा कम से कम 2 वर्णों के बाद फ़िल्टर की गई सरणी है। मुझे पता है कि यह व्युत्पन्न डेटा है और राज्य में इसे संग्रहीत करने के बारे में ऐसा तर्क दिया जा सकता है, लेकिन इसके लिए आवश्यक हैcurrentlySelectedIndex
फ़िल्टर्ड सूची से वर्तमान में चयनित तत्व का सूचकांक क्या है।Input
घटक में उपयोगकर्ता प्रकार 2 से अधिक अक्षर हैं, सरणी फ़िल्टर की जाती है और फ़िल्टर किए गए सरणी में प्रत्येक प्रविष्टि के लिए एकResult
घटक प्रदान किया जाता हैप्रत्येक
Result
घटक पूर्ण पथ प्रदर्शित कर रहा है जो आंशिक रूप से क्वेरी से मेल खाता है, और पथ का आंशिक मिलान भाग हाइलाइट किया गया है। उदाहरण के लिए एक परिणाम घटक के DOM, अगर उपयोगकर्ता टाइप किया था 'le' कुछ इस तरह होगा:<li>this/is/a/fi<strong>le</strong>/path</li>
- यदि उपयोगकर्ता अप या डाउन कीज दबाता है जबकि
Input
घटक एरे केcurrentlySelectedIndex
आधार पर बदलाव पर केंद्रित हैfiltered
। यह उसResult
घटक का कारण बनता है जो अनुक्रमणिका से मिलान के रूप में चिह्नित किया जाता है जिससे पुन: रेंडर किया जाता है
मुसीबत
शुरू में मैंने files
रिएक्ट के विकास संस्करण का उपयोग करते हुए एक छोटे से पर्याप्त सरणी के साथ यह परीक्षण किया , और सभी ने ठीक काम किया।
समस्या तब दिखाई दी जब मुझे files
10000 प्रविष्टियों के रूप में एक सरणी से निपटना पड़ा । इनपुट में 2 अक्षर टाइप करने से एक बड़ी सूची बन जाएगी और जब मैंने इसे नेविगेट करने के लिए अप और डाउन कीज़ को दबाया तो यह बहुत ही खराब होगा।
पहले मेरे पास Result
तत्वों के लिए एक परिभाषित घटक नहीं था और मैं केवल Search
घटक के प्रत्येक रेंडर पर मक्खी पर सूची बना रहा था , जैसे कि:
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));
जैसा कि आप बता सकते हैं, हर बार currentlySelectedIndex
बदले जाने पर, यह फिर से रेंडर का कारण बनता है और सूची को हर बार फिर से बनाया जाएगा। मैंने सोचा था कि चूंकि मैंने key
प्रत्येक li
तत्व पर एक मूल्य निर्धारित किया था, इसलिए रिएक्ट हर दूसरे li
तत्व को फिर से प्रस्तुत करने से बचता है जिसमें इसका className
परिवर्तन नहीं था , लेकिन जाहिर है कि ऐसा नहीं था।
मैंने Result
तत्वों के लिए एक वर्ग को परिभाषित करते हुए समाप्त किया , जहां यह स्पष्ट रूप से जांच करता है कि क्या प्रत्येक Result
तत्व को फिर से प्रस्तुत करना चाहिए या नहीं, यह इस आधार पर कि वर्तमान उपयोगकर्ता इनपुट पर आधारित है:
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>
);
}
});
और सूची अब इस प्रकार बनाई गई है:
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));
}
इससे प्रदर्शन थोड़ा बेहतर हुआ, लेकिन यह अभी भी काफी अच्छा नहीं है। बात यह है कि जब मैंने रिएक्ट चीजों के प्रोडक्शन वर्जन पर परीक्षण किया तो इसमें काफी चिकनी, बिना किसी अंतराल के काम किया।
जमीनी स्तर
प्रतिक्रिया के विकास और उत्पादन संस्करणों के बीच ऐसी ध्यान देने योग्य विसंगति सामान्य है?
क्या मैं समझ रहा हूं / कुछ गलत कर रहा हूं, जब मुझे लगता है कि रिएक्ट सूची को कैसे प्रबंधित करता है?
UPDATE 14-11-2016
मुझे माइकल जैक्सन की यह प्रस्तुति मिली है, जहाँ वह इस मुद्दे को बहुत हद तक इसी तरह से निपटाता है: https://youtu.be/7S8v8jfLb1Q?t=26m2s
समाधान नीचे AskarovBeknar के उत्तर द्वारा प्रस्तावित एक के समान है
अद्यतन 14-4-2018
चूंकि यह स्पष्ट रूप से एक लोकप्रिय सवाल है और मूल प्रश्न पूछे जाने के बाद से चीजें आगे बढ़ी हैं, जबकि मैं आपको ऊपर दिए गए वीडियो को देखने के लिए प्रोत्साहित करता हूं, ताकि एक आभासी लेआउट की समझ प्राप्त कर सके, मैं आपको रिएक्ट वर्चुअलाइज्ड का उपयोग करने के लिए भी प्रोत्साहित करता हूं। पुस्तकालय यदि आप पहिया का फिर से आविष्कार नहीं करना चाहते हैं।