प्रतिक्रिया के साथ बड़ी सूची प्रदर्शन


86

मैं रिएक्ट के साथ एक फिल्टर करने योग्य सूची को लागू करने की प्रक्रिया में हूं। सूची की संरचना नीचे दी गई छवि में दिखाई गई है।

यहां छवि विवरण दर्ज करें

आधार

यहां बताया गया है कि यह कैसे काम करने वाला है:

  • राज्य उच्चतम स्तर के घटक, घटक में रहता है 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रिएक्ट के विकास संस्करण का उपयोग करते हुए एक छोटे से पर्याप्त सरणी के साथ यह परीक्षण किया , और सभी ने ठीक काम किया।

समस्या तब दिखाई दी जब मुझे files10000 प्रविष्टियों के रूप में एक सरणी से निपटना पड़ा । इनपुट में 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

चूंकि यह स्पष्ट रूप से एक लोकप्रिय सवाल है और मूल प्रश्न पूछे जाने के बाद से चीजें आगे बढ़ी हैं, जबकि मैं आपको ऊपर दिए गए वीडियो को देखने के लिए प्रोत्साहित करता हूं, ताकि एक आभासी लेआउट की समझ प्राप्त कर सके, मैं आपको रिएक्ट वर्चुअलाइज्ड का उपयोग करने के लिए भी प्रोत्साहित करता हूं। पुस्तकालय यदि आप पहिया का फिर से आविष्कार नहीं करना चाहते हैं।


प्रतिक्रिया के विकास / उत्पादन संस्करण से आपका क्या अभिप्राय है?
दिबिज्र


आह, मैं देख रहा हूँ, धन्यवाद। तो आपके एक प्रश्न का उत्तर देने के लिए, यह कहता है कि संस्करणों के बीच अनुकूलन में विसंगति है। बड़ी सूचियों में देखने के लिए एक चीज आपके रेंडर में फ़ंक्शन बना रही है। जब आप विशाल सूचियों में आते हैं तो इसमें एक प्रदर्शन हिट होगा। मैं कोशिश करूंगा और देखूंगा कि उनके पूर्ण टूल facebook.github.io/react/docs/perf.html
Dibesjr

2
मुझे लगता है कि आपको Redux का उपयोग करके पुनर्विचार करना चाहिए क्योंकि यह वास्तव में आपको यहाँ (या किसी भी प्रकार के प्रवाह कार्यान्वयन) की आवश्यकता है। आपको निश्चित रूप से इस प्रस्तुति पर एक नज़र
डालनी

2
मुझे संदेह है कि उपयोगकर्ता को 10000 परिणामों के माध्यम से स्क्रॉल करने का कोई लाभ है। तो क्या हुआ अगर आप केवल शीर्ष -100 परिणाम या तो प्रस्तुत करते हैं, और क्वेरी के आधार पर इन्हें अपडेट करते हैं।
कोएन।

जवाबों:


18

इस सवाल के अन्य जवाबों में से कई के साथ मुख्य समस्या इस तथ्य में निहित है कि डोम में इतने सारे तत्वों को फ़िल्टर करना और प्रमुख घटनाओं को संभालना धीमा है।

आप रिएक्ट के संबंध में स्वाभाविक रूप से कुछ भी गलत नहीं कर रहे हैं जो कि समस्या का कारण बन रहा है लेकिन कई मुद्दे जो यूआई से संबंधित प्रदर्शन कर रहे हैं जैसे दोष का एक बड़ा प्रतिशत भी ले सकते हैं।

यदि आपका UI कार्यकुशलता को ध्यान में रखते हुए डिज़ाइन नहीं किया गया है, तो रिएक्ट जैसे उपकरण जो प्रदर्शन करने के लिए डिज़ाइन किए गए हैं, वे पीड़ित होंगे।

परिणाम सेट को फ़िल्टर करना, @Koen द्वारा उल्लिखित एक शानदार शुरुआत है

मैंने विचार के साथ थोड़ा सा खेला है और एक उदाहरण ऐप बनाया है जो बताता है कि मैं इस तरह की समस्या से कैसे निपट सकता हूं।

यह किसी भी तरह से production readyकोड नहीं है, लेकिन यह अवधारणा को पर्याप्त रूप से चित्रित करता है और इसे और अधिक मजबूत करने के लिए संशोधित किया जा सकता है, कोड पर एक नज़र डालने के लिए स्वतंत्र महसूस करता हूं - मुझे उम्मीद है कि बहुत कम से कम यह आपको कुछ विचार देता है ...;)

प्रतिक्रिया-बड़े सूची-उदाहरण

यहां छवि विवरण दर्ज करें


1
मुझे वास्तव में सिर्फ एक उत्तर का चयन करने में बुरा लगता है, वे सभी उन में लगाए गए प्रयास लगते हैं, लेकिन मैं वर्तमान में बिना पीसी के साथ छुट्टी पर हूं और वास्तव में उन्हें ध्यान से देखने की ज़रूरत नहीं है। मैंने इसे एक चुना क्योंकि यह एक फोन से पढ़ते समय भी समझने के लिए पर्याप्त और बिंदु तक कम है। लंगड़ा कारण मुझे पता है।
दिमित्रीस करागियानिसिस

होस्ट फ़ाइल को संपादित करने से आपका क्या मतलब है 127.0.0.1 * http://localhost:3001?
स्टैकजेली

@stackjlei मुझे लगता है कि उनका मतलब 127.0.0.1 मैपिंग टू लोकलहोस्ट: 3001 इन / इत्यादि / होस्ट्स
Maverick

16

एक बहुत ही समान समस्या के साथ मेरा अनुभव यह है कि प्रतिक्रिया वास्तव में पीड़ित होती है यदि एक ही बार में 100-200 से अधिक या डोम में घटक होते हैं। भले ही आप shouldComponentUpdateफिर से रेंडर पर एक या दो घटकों को बदलने के लिए केवल सुपर सावधान (अपनी सभी चाबियाँ और / या एक विधि लागू करके ) कर रहे हैं, आप अभी भी चोट की दुनिया में जा रहे हैं।

पल में प्रतिक्रिया का धीमा हिस्सा तब होता है जब यह आभासी डोम और वास्तविक डोम के बीच अंतर की तुलना करता है। यदि आपके पास हजारों घटक हैं, लेकिन केवल एक जोड़े को अपडेट करते हैं, तो इससे कोई फर्क नहीं पड़ता, प्रतिक्रिया अभी भी DOM के बीच करने के लिए बड़े पैमाने पर अंतर ऑपरेशन है।

जब मैं अब पृष्ठ लिखता हूं तो मैं उन्हें घटकों की संख्या को कम करने के लिए डिजाइन करने का प्रयास करता हूं, घटकों की बड़ी सूची प्रदान करते समय ऐसा करने का एक तरीका है ... अच्छी तरह से ... घटकों की बड़ी सूची को प्रस्तुत न करें।

मेरा क्या मतलब है: केवल उन घटकों को प्रस्तुत करें जिन्हें आप वर्तमान में देख सकते हैं, जितना आप नीचे स्क्रॉल करते हैं उतना अधिक प्रस्तुत करें, आप उपयोगकर्ता को किसी भी तरह से हजारों घटकों के माध्यम से नीचे स्क्रॉल करने की संभावना नहीं है .... मुझे उम्मीद है।

ऐसा करने के लिए एक महान पुस्तकालय है:

https://www.npmjs.com/package/react-infinite-scroll

एक महान के साथ यहाँ कैसे:

http://www.reactexamples.com/react-infinite-scroll/

मुझे डर है कि यह उन घटकों को नहीं हटाता जो पृष्ठ के शीर्ष पर हैं, इसलिए यदि आप लंबे समय तक स्क्रॉल करते हैं तो आप प्रदर्शन के मुद्दे फिर से शुरू करेंगे।

मुझे पता है कि उत्तर के रूप में एक लिंक प्रदान करना अच्छा अभ्यास नहीं है, लेकिन वे जो उदाहरण प्रदान करते हैं, वे बताते हैं कि इस पुस्तकालय का उपयोग करने की तुलना में मैं यहां कितना बेहतर हूं। उम्मीद है कि मैंने समझाया है कि बड़ी सूची खराब क्यों होती है, लेकिन यह भी एक काम है।


2
अद्यतन: पैकेज जो इस उत्तर में है, उसे बनाए नहीं रखा गया है। एक कांटा npmjs.com/package/react-infinite-scroller
अली अल अमीन

11

सबसे पहले, रिएक्ट के विकास और उत्पादन संस्करण के बीच का अंतर बहुत बड़ा है क्योंकि उत्पादन में कई बायपास किए गए विवेक जांच (जैसे कि प्रोप प्रकार सत्यापन) हैं।

फिर, मुझे लगता है कि आपको Redux का उपयोग करने पर पुनर्विचार करना चाहिए क्योंकि यह यहाँ आपके लिए आवश्यक है (या किसी भी प्रकार के प्रवाह कार्यान्वयन) के लिए। आपको निश्चित रूप से इस प्रस्तुति पर एक नज़र डालनी चाहिए: बिग सूची उच्च प्रदर्शन प्रतिक्रिया और रिडक्स

लेकिन रिडक्स में गोता लगाने से पहले, आपको अपने घटकों को छोटे घटकों में विभाजित करके अपने रिएक्ट कोड में कुछ अन्याय करने की आवश्यकता है क्योंकि shouldComponentUpdateबच्चों के प्रतिपादन को पूरी तरह से बायपास किया जाएगा, इसलिए यह एक बहुत बड़ा लाभ है

जब आपके पास अधिक दानेदार घटक होते हैं, तो आप डेटा प्रवाह को बेहतर ढंग से व्यवस्थित करने के लिए राज्य को रिडक्स और प्रतिक्रिया-रिडक्स के साथ संभाल सकते हैं।

मैं हाल ही में इसी तरह के मुद्दे का सामना कर रहा था जब मुझे एक हजार पंक्तियों को प्रस्तुत करने की आवश्यकता थी और इसकी सामग्री को संपादित करके प्रत्येक पंक्ति को संशोधित करने में सक्षम हो। यह मिनी ऐप संभावित डुप्लिकेट संगीत कार्यक्रमों के साथ संगीत कार्यक्रमों की एक सूची प्रदर्शित करता है और मुझे प्रत्येक संभावित डुप्लिकेट के लिए चुना जाना चाहिए, अगर मैं चेकबॉक्स की जांच करके एक मूल कॉन्सर्ट (डुप्लिकेट नहीं) के रूप में संभावित डुप्लिकेट को चिह्नित करना चाहता हूं, और, यदि आवश्यक हो, तो संपादित करें संगीत कार्यक्रम का नाम। यदि मैं किसी विशेष संभावित डुप्लिकेट आइटम के लिए कुछ नहीं करता हूं, तो इसे डुप्लिकेट माना जाएगा और हटा दिया जाएगा।

यहां है कि यह कैसा लग रहा है :

यहां छवि विवरण दर्ज करें

मूल रूप से 4 मुख्य घटक हैं (यहां केवल एक पंक्ति है लेकिन यह उदाहरण के लिए है):

यहां छवि विवरण दर्ज करें

: यहाँ पूर्ण कोड (कार्य CodePen है प्रतिक्रिया और Redux के साथ विशाल सूची का उपयोग करके) redux , -redux प्रतिक्रिया , अपरिवर्तनीय , फिर से चुनें और संयोजित :

const initialState = Immutable.fromJS({ /* See codepen, this is a HUGE list */ })

const types = {
    CONCERTS_DEDUP_NAME_CHANGED: 'diggger/concertsDeduplication/CONCERTS_DEDUP_NAME_CHANGED',
    CONCERTS_DEDUP_CONCERT_TOGGLED: 'diggger/concertsDeduplication/CONCERTS_DEDUP_CONCERT_TOGGLED',
};

const changeName = (pk, name) => ({
    type: types.CONCERTS_DEDUP_NAME_CHANGED,
    pk,
    name
});

const toggleConcert = (pk, toggled) => ({
    type: types.CONCERTS_DEDUP_CONCERT_TOGGLED,
    pk,
    toggled
});


const reducer = (state = initialState, action = {}) => {
    switch (action.type) {
        case types.CONCERTS_DEDUP_NAME_CHANGED:
            return state
                .updateIn(['names', String(action.pk)], () => action.name)
                .set('_state', 'not_saved');
        case types.CONCERTS_DEDUP_CONCERT_TOGGLED:
            return state
                .updateIn(['concerts', String(action.pk)], () => action.toggled)
                .set('_state', 'not_saved');
        default:
            return state;
    }
};

/* configureStore */
const store = Redux.createStore(
    reducer,
    initialState
);

/* SELECTORS */

const getDuplicatesGroups = (state) => state.get('duplicatesGroups');

const getDuplicateGroup = (state, name) => state.getIn(['duplicatesGroups', name]);

const getConcerts = (state) => state.get('concerts');

const getNames = (state) => state.get('names');

const getConcertName = (state, pk) => getNames(state).get(String(pk));

const isConcertOriginal = (state, pk) => getConcerts(state).get(String(pk));

const getGroupNames = reselect.createSelector(
    getDuplicatesGroups,
    (duplicates) => duplicates.flip().toList()
);

const makeGetConcertName = () => reselect.createSelector(
    getConcertName,
    (name) => name
);

const makeIsConcertOriginal = () => reselect.createSelector(
    isConcertOriginal,
    (original) => original
);

const makeGetDuplicateGroup = () => reselect.createSelector(
    getDuplicateGroup,
    (duplicates) => duplicates
);



/* COMPONENTS */

const DuplicatessTableRow = Recompose.onlyUpdateForKeys(['name'])(({ name }) => {
    return (
        <tr>
            <td>{name}</td>
            <DuplicatesRowColumn name={name}/>
        </tr>
    )
});

const PureToggle = Recompose.onlyUpdateForKeys(['toggled'])(({ toggled, ...otherProps }) => (
    <input type="checkbox" defaultChecked={toggled} {...otherProps}/>
));


/* CONTAINERS */

let DuplicatesTable = ({ groups }) => {

    return (
        <div>
            <table className="pure-table pure-table-bordered">
                <thead>
                    <tr>
                        <th>{'Concert'}</th>
                        <th>{'Duplicates'}</th>
                    </tr>
                </thead>
                <tbody>
                    {groups.map(name => (
                        <DuplicatesTableRow key={name} name={name} />
                    ))}
                </tbody>
            </table>
        </div>
    )

};

DuplicatesTable.propTypes = {
    groups: React.PropTypes.instanceOf(Immutable.List),
};

DuplicatesTable = ReactRedux.connect(
    (state) => ({
        groups: getGroupNames(state),
    })
)(DuplicatesTable);


let DuplicatesRowColumn = ({ duplicates }) => (
    <td>
        <ul>
            {duplicates.map(d => (
                <DuplicateItem
                    key={d}
                    pk={d}/>
            ))}
        </ul>
    </td>
);

DuplicatessRowColumn.propTypes = {
    duplicates: React.PropTypes.arrayOf(
        React.PropTypes.string
    )
};

const makeMapStateToProps1 = (_, { name }) => {
    const getDuplicateGroup = makeGetDuplicateGroup();
    return (state) => ({
        duplicates: getDuplicateGroup(state, name)
    });
};

DuplicatesRowColumn = ReactRedux.connect(makeMapStateToProps1)(DuplicatesRowColumn);


let DuplicateItem = ({ pk, name, toggled, onToggle, onNameChange }) => {
    return (
        <li>
            <table>
                <tbody>
                    <tr>
                        <td>{ toggled ? <input type="text" value={name} onChange={(e) => onNameChange(pk, e.target.value)}/> : name }</td>
                        <td>
                            <PureToggle toggled={toggled} onChange={(e) => onToggle(pk, e.target.checked)}/>
                        </td>
                    </tr>
                </tbody>
            </table>
        </li>
    )
}

const makeMapStateToProps2 = (_, { pk }) => {
    const getConcertName = makeGetConcertName();
    const isConcertOriginal = makeIsConcertOriginal();

    return (state) => ({
        name: getConcertName(state, pk),
        toggled: isConcertOriginal(state, pk)
    });
};

DuplicateItem = ReactRedux.connect(
    makeMapStateToProps2,
    (dispatch) => ({
        onNameChange(pk, name) {
            dispatch(changeName(pk, name));
        },
        onToggle(pk, toggled) {
            dispatch(toggleConcert(pk, toggled));
        }
    })
)(DuplicateItem);


const App = () => (
    <div style={{ maxWidth: '1200px', margin: 'auto' }}>
        <DuplicatesTable />
    </div>
)

ReactDOM.render(
    <ReactRedux.Provider store={store}>
        <App/>
    </ReactRedux.Provider>,
    document.getElementById('app')
);

विशाल डेटासेट के साथ काम करने पर इस मिनी ऐप को सीखकर सबक

  • रिएक्ट घटक सबसे अच्छा काम करते हैं जब उन्हें छोटा रखा जाता है
  • पुनर्संयोजन से बचने और एक ही संदर्भ वस्तु (अपरिवर्तनीय का उपयोग करते समय) को रखने के लिए रीसेलेट बहुत उपयोगी हो जाता है।
  • connectघटक के लिए एड कंपोनेंट बनाएं जो डेटा के सबसे नज़दीक हों उन्हें कंपोनेंट से गुजरने से बचने की ज़रूरत होती है जो वे उपयोग नहीं करते हैं
  • मानचित्र बनाने के लिए फैब्रिक फ़ंक्शन का उपयोग जब आप केवल ownPropsअनुपयोगी री-रेंडरिंग से बचने के लिए दिए गए प्रारंभिक प्रॉप की आवश्यकता हो तो
  • प्रतिक्रिया और निश्चित रूप से एक साथ रॉक!

2
मुझे नहीं लगता कि ओपी की समस्या को हल करने के लिए रिडक्स पर निर्भरता को जोड़ना आवश्यक है, उसके परिणाम सेट को फ़िल्टर करने के लिए और अधिक प्रेषण की कार्रवाई केवल समस्या को जटिल करेगी, डिस्पैच उतना सस्ता नहीं है जितना आप सोच सकते हैं, स्थानीय घटक के साथ इस विशेष स्थिति को संभालना राज्य सबसे कुशल दृष्टिकोण है
जुऑ

4
  1. विकास प्रक्रिया को आसान बनाने के लिए प्रत्येक घटक के प्रोपेप्टिस के लिए विकास संस्करण की जाँच में प्रतिक्रिया, जबकि उत्पादन में इसे छोड़ दिया जाता है।

  2. स्ट्रिंग्स की फ़िल्टरिंग सूची हर कीअप के लिए बहुत महंगा ऑपरेशन है। यह जावास्क्रिप्ट की एकल थ्रेडेड प्रकृति के कारण प्रदर्शन समस्याओं का कारण हो सकता है। समाधान हो सकता है कि विलम्ब की अवधि समाप्त होने तक अपने फ़िल्टर फ़ंक्शन के निष्पादन में देरी करने के लिए डेबिट विधि का उपयोग किया जाए।

  3. एक और समस्या स्वयं विशाल सूची हो सकती है। आप वर्चुअल लेआउट बना सकते हैं और बनाए गए आइटमों का पुन: उपयोग कर सकते हैं बस डेटा की जगह ले सकते हैं। मूल रूप से आप तय ऊंचाई के साथ स्क्रॉल करने योग्य कंटेनर घटक बनाते हैं, जिसके अंदर आप सूची कंटेनर रखेंगे। सूची कंटेनर की ऊंचाई मैन्युअल रूप से सेट की जानी चाहिए (आइटमहाइट * नंबरऑफइमेंस) दृश्य सूची की लंबाई के आधार पर, एक स्क्रॉलबार काम करने के लिए। फिर कुछ आइटम घटक बनाएं ताकि वे स्क्रॉल करने योग्य कंटेनरों की ऊँचाई को भर दें और शायद अतिरिक्त एक या दो नकल निरंतर सूची प्रभाव जोड़ दें। उन्हें पूर्ण स्थान दें और स्क्रॉल पर बस अपनी स्थिति को स्थानांतरित करें ताकि यह निरंतर सूची की नकल करेगा (मुझे लगता है कि आपको पता चल जाएगा कि कैसे लागू किया जाए :)

  4. एक और बात डोम को लिखना भी महंगा ऑपरेशन है, खासकर अगर आप इसे गलत करते हैं। आप सूची प्रदर्शित करने के लिए कैनवास का उपयोग कर सकते हैं और स्क्रॉल पर सहज अनुभव बना सकते हैं। चेकआउट प्रतिक्रिया-कैनवास घटक। मैंने सुना है कि वे पहले से ही सूचियों पर कुछ काम कर चुके हैं।


के बारे में कोई जानकारी React in development? और प्रत्येक घटक के प्रोटॉयटैप्स के लिए जांच क्यों?
लिउइल

4

रिएक्ट वर्चुअलाइज्ड सिलेक्ट की जाँच करें, यह इस मुद्दे को संबोधित करने के लिए डिज़ाइन किया गया है और मेरे अनुभव में प्रभावशाली प्रदर्शन करता है। विवरण से:

HOC जो ड्रॉप-डाउन में विकल्पों की बड़ी सूची प्रदर्शित करने के लिए प्रतिक्रिया-वर्चुअलाइज्ड और प्रतिक्रिया-चयन का उपयोग करती है

https://github.com/bvaughn/react-virtualized-select


4

जैसा कि मैंने अपनी टिप्पणी में उल्लेख किया है , मुझे संदेह है कि उपयोगकर्ताओं को एक ही बार में ब्राउज़र में उन सभी 10000 परिणामों की आवश्यकता होती है।

क्या होगा यदि आप परिणामों के माध्यम से पेज करते हैं, और हमेशा सिर्फ 10 परिणामों की सूची दिखाते हैं।

मैंने Redux जैसी किसी अन्य लाइब्रेरी का उपयोग किए बिना, इस तकनीक का उपयोग करके एक उदाहरण बनाया है । वर्तमान में केवल कीबोर्ड नेविगेशन के साथ, लेकिन स्क्रॉलिंग पर भी काम करने के लिए इसे आसानी से बढ़ाया जा सकता है।

उदाहरण 3 घटकों, कंटेनर एप्लिकेशन, एक खोज घटक और एक सूची घटक से मौजूद है। लगभग सभी तर्क कंटेनर घटक में स्थानांतरित कर दिए गए हैं।

जिस्ट का startऔर selectedपरिणाम का ध्यान रखने और कीबोर्ड इंटरेक्शन पर शिफ्ट करने में निहित है ।

nextResult: function() {
  var selected = this.state.selected + 1
  var start = this.state.start
  if(selected >= start + this.props.limit) {
    ++start
  }
  if(selected + start < this.state.results.length) {
    this.setState({selected: selected, start: start})
  }
},

prevResult: function() {
  var selected = this.state.selected - 1
  var start = this.state.start
  if(selected < start) {
    --start
  }
  if(selected + start >= 0) {
    this.setState({selected: selected, start: start})
  }
},

बस एक फिल्टर के माध्यम से सभी फ़ाइलों को पारित करते हुए:

updateResults: function() {
  var results = this.props.files.filter(function(file){
    return file.file.indexOf(this.state.query) > -1
  }, this)

  this.setState({
    results: results
  });
},

और के आधार पर परिणाम टुकड़ा करने की क्रिया startऔर limitमें renderविधि:

render: function() {
  var files = this.state.results.slice(this.state.start, this.state.start + this.props.limit)
  return (
    <div>
      <Search onSearch={this.onSearch} onKeyDown={this.onKeyDown} />
      <List files={files} selected={this.state.selected - this.state.start} />
    </div>
  )
}

पूरी तरह से काम कर रहे उदाहरण के साथ: https://jsfiddle.net/koenpunt/hm1xnpqk/


3

रिएक्ट घटक में लोड करने से पहले फ़िल्टर का प्रयास करें और केवल घटक में उचित मात्रा में आइटम दिखाएं और मांग पर अधिक लोड करें। कोई भी एक समय में कई वस्तुओं को नहीं देख सकता है।

मुझे नहीं लगता कि आप हैं, लेकिन कुंजी के रूप में अनुक्रमित का उपयोग न करें

विकास और उत्पादन संस्करण भिन्न होने के वास्तविक कारण जानने के लिए आप profilingअपने कोड को आज़मा सकते हैं।

अपना पृष्ठ लोड करें, रिकॉर्डिंग शुरू करें, एक बदलाव करें, रिकॉर्डिंग बंद करें और फिर समय की जांच करें। Chrome में प्रदर्शन रूपरेखा के निर्देशों के लिए यहां देखें ।


2

इस समस्या से जूझ रहे किसी भी व्यक्ति के लिए मैंने एक घटक लिखा है react-big-listजो सूचियों को 1 मिलियन रिकॉर्ड तक संभालता है।

शीर्ष पर यह कुछ फैंसी अतिरिक्त सुविधाओं के साथ आता है जैसे:

  • छंटाई
  • कैशिंग
  • कस्टम फ़िल्टरिंग
  • ...

हम इसे काफी कुछ एप्स में प्रोडक्शन में इस्तेमाल कर रहे हैं और यह बढ़िया काम करता है।


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.