2016-02-15 13 views
9

हटाते समय गलत पंक्ति हटा दी गई है मुझे पता है कि इससे पहले पूछा गया है, उदाहरण के लिए here, here और here देखें।प्रतिक्रिया मूल सूची देखें:

हालांकि, कोई भी उत्तर/टिप्पणियां संतोषजनक नहीं हैं। वे या तो आपको उस डेटा को क्लोन करने के लिए कहते हैं जो समस्या का समाधान नहीं करता है या ListView पर एक अनन्य कुंजी सेट करने के लिए जो समस्या हल करता है लेकिन एक नया बनाता है।

जब आप ListView पर एक अनन्य कुंजी सेट करते हैं और इसे हटाने के बाद इसे अपडेट करते हैं तो संपूर्ण दृश्य फिर से प्रस्तुत होता है और शीर्ष पर स्क्रॉल करता है। एक उपयोगकर्ता जो किसी आइटम को हटाने के लिए सूची को स्क्रॉल करता है, उसकी अपेक्षा रखने के लिए सूची की स्थिति की अपेक्षा करता है।

यहाँ एक काल्पनिक उदाहरण है, का उपयोग करते हुए मैं क्या ग्रहण करेंगे डेटा क्लोनिंग का सही तरीका था:

var ListViewExample = React.createClass({ 

    getInitialState() { 
    var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => { 
     r1 !== r2 
    }}); 
    var rows = ['row 1', 'row 2', 'row 3']; 
    return { 
     dataSource: ds.cloneWithRows(rows), 
    }; 
    }, 

    _deleteRow() { 
    var rows = ['row 1', 'row 3']; 
    this.setState({dataSource: this.state.dataSource.cloneWithRows(rows)}) 
    }, 

    renderRow(rowData, sectionID, rowID) { 
    return <TouchableOpacity onPress={this._deleteRow} 
     style={{height: 60, flex: 1, borderBottomWidth: 1}}> 
     <Text>{rowData}</Text> 
    </TouchableOpacity> 
    }, 

    render() { 
    return (
     <ListView 
     dataSource={this.state.dataSource} 
     renderRow={this.renderRow} 
     /> 
    ); 
    } 

}); 

और here आप कार्रवाई जहां गलत पंक्ति मिलता है हटाया में इसके बारे में एक gif देख सकते हैं। विकल्प, सूची दृश्य के key प्रोप को सेट करने के लिए सही पंक्ति को हटा देता है लेकिन जैसा कि मैंने कहा है कि सूची शीर्ष पर स्क्रॉल करने का कारण बन जाएगी।

अद्यतन

मैं पहले से ही नीचे नादर के जवाब स्वीकार कर लिया है, लेकिन यह क्योंकि यह डेटा स्रोत पर rowHasChanged फोन नहीं करता है सही तरीके से होना प्रतीत नहीं होता है। यह ListView दस्तावेज़ों के अनुरूप नहीं है। यह मेरी समस्या का समाधान तो मैं यह जवाब के रूप में चिह्नित छोड़ देंगे किया, लेकिन मैं महसूस कर रही है कि यह एक वैकल्पिक हल के बजाय सही समाधान

कोई अन्य अपडेट है

ठीक है यह अजीब है, लेकिन मेरी rowHasChanged समारोह था return कथन गायब है। मुझे लगता है कि मेरी कॉफी में बहुत ज्यादा ES6 चीनी।

तो निष्कर्ष में, यदि आप अपने rowHasChanged फ़ंक्शन को खराब करते हैं, तो this._ds कुछ कारणों से काम करेगा।

this.setState({ 
    dataSource: this.state.dataSource.cloneWithRows(rows) 
}); 

अपने dataSource को अपडेट करते समय: आप चीजों को सही तरीके से आप के साथ शुरू करने के लिए शायद की तरह कुछ का उपयोग करना चाहिए करते हैं।

यह भी याद रखें कि आपको एक नया rows डेटाब्लोब चाहिए। cloneWithRows(rows.push(newRow) जैसे कुछ के साथ इसे म्यूट करना जबकि काम नहीं करेगा जबकि cloneWithRows(rows.concat([newRow]) होगा।

+0

यदि यह मदद करता है किसी और को ... के लिए मुझे क्लोनिंग से पहले अपनी सूची की एक गहरी प्रतिलिपि बना रही थी ... कुंजी तो इससे पहले कि cloneWithRows कर new_rows = [... पंक्तियों] –

उत्तर

5

मुझे लगता है कि समस्या यह है कि आप पिछले ListView.DataSource उदाहरण के आधार पर अपना डेटास्रोत सेट कर रहे हैं। मैंने here के बारे में जो बात कर रहा हूं उसका एक डेमो स्थापित किया है, और इसे करने के दूसरे तरीके के साथ नीचे दिया गया उदाहरण डाला है।

यह करके देखें:

'use strict'; 

var React = require('react-native'); 
var { 
    AppRegistry, 
    StyleSheet, 
    Text, 
    View, 
    TouchableOpacity, 
    ListView 
} = React; 

var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => { r1 !== r2 }}); 

var SampleApp = React.createClass({ 

    getInitialState() { 
    var rows = ['row 1', 'row 2', 'row 3']; 
    return { 
     dataSource: ds.cloneWithRows(rows), 
    }; 
    }, 

    _deleteRow() { 
    var rows = ['row 1', 'row 3']; 
    this.setState({dataSource: ds.cloneWithRows(rows)}) 
    }, 

    renderRow(rowData, sectionID, rowID) { 
    return <TouchableOpacity onPress={this._deleteRow} 
     style={{height: 60, flex: 1, borderBottomWidth: 1}}> 
     <Text>{rowData}</Text> 
    </TouchableOpacity> 
    }, 

    render() { 
    return (
     <ListView 
     dataSource={this.state.dataSource} 
     renderRow={this.renderRow} 
     /> 
    ); 
    } 

}); 

https://rnplay.org/apps/YGBcIA

तुम भी renderRow में rowID उपयोग कर सकते हैं अपने हटाने समारोह में आइटम आप हटाना चाहते हैं पहचानें, फिर, डेटा स्रोत की स्थिति को रीसेट।

उदाहरण देखें कि मैंने here सेट किया है।इसके अलावा, कोड के नीचे है:

'use strict'; 

var React = require('react-native'); 
var { 
    AppRegistry, 
    StyleSheet, 
    Text, 
    View, 
    TouchableOpacity, 
    ListView 
} = React; 

var rows = ['row 1', 'row 2', 'row 3']; 
var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => { 
     r1 !== r2 
    }}); 

var SampleApp = React.createClass({ 

    getInitialState() { 

    return { 
     dataSource: ds.cloneWithRows([]), 
     rows: rows 
    }; 
    }, 

    componentDidMount() { 
    this.setState({ 
     dataSource: ds.cloneWithRows(this.state.rows) 
    }) 
    }, 

    _deleteRow(rowID) { 
    this.state.rows.splice(rowID, 1) 
    this.setState({ 
     dataSource: ds.cloneWithRows(this.state.rows), 
    }) 
    }, 

    renderRow(rowData, sectionID, rowID) { 
    return <TouchableOpacity onPress={() => this._deleteRow(rowID) } 
     style={{height: 60, flex: 1, borderBottomWidth: 1}}> 
     <Text>{rowData}</Text> 
    </TouchableOpacity> 
    }, 

    render() { 
    return (
     <ListView 
     dataSource={this.state.dataSource} 
     renderRow={this.renderRow} 
     /> 
    ); 
    } 

}); 
var styles = StyleSheet.create({ 
    container: { 
    flex: 1, 
    justifyContent: 'center', 
    alignItems: 'center', 
    backgroundColor: '#F5FCFF', 
    }, 
    welcome: { 
    fontSize: 28, 
    textAlign: 'center', 
    margin: 10, 
    }, 
    instructions: { 
    textAlign: 'center', 
    color: '#333333', 
    fontSize: 19, 
    marginBottom: 5, 
    }, 
}); 

AppRegistry.registerComponent('SampleApp',() => SampleApp); 
+1

आप बिल्कुल सही हैं। धन्यवाद! रिएक्ट नेटिव वेबसाइट पर मूवी ट्यूटोरियल के साथ-साथ ListView के लिए प्रलेखन ने नए डेटा को 'डेटासोर्स: this.state.dataSource.cloneWithRows' के साथ सेट किया है, इसलिए मुझे लगता है कि मैंने इसे अपना रास्ता नहीं माना पहले। फिर से धन्यवाद! –

+0

बहुत बढ़िया, हाँ ListView पर दस्तावेज़ ठीक हैं लेकिन वे सबसे अच्छे नहीं हैं। मैं इस समय एक पुल अनुरोध पर काम कर रहा हूं, उम्मीद है कि वे सोचेंगे कि यह समझ में आता है! –

+0

मैंने अभी देखा है कि ऊपर वर्णित विधि का उपयोग करके, 'rowHasChanged' को कॉल नहीं किया जाता है। आप वहां कंसोल लॉग डालकर इसे सत्यापित कर सकते हैं। यह इरादा व्यवहार नहीं हो सकता है, है ना? और जैसे मैंने कहा, प्रतिक्रिया मूल दस्तावेज़ कुछ वैश्विक 'डीएस 'ऑब्जेक्ट पर' ds.cloneWithRows' के बजाय 'this.state.dataSource.cloneWithRows' के साथ राज्य को अपडेट करते हैं। –

संबंधित मुद्दे