私はこの問題を長い間解決するために本当に懸命に取り組んできました。React Native - 完全に再レンダリングせずにListViewにデータを追加して追加する方法
私は解決策についてStackOverflowとその他の問題を見てきましたが、明確な問題が見つかりませんでした。
私は完全な再レンダリングを前に置くことができることを知っていますが、どのようにプリレンダリングを完全に再描画することができないのか分かりません。
私はリストビューにデータをアップロードするときに非インデックスキーでこれを達成できると思いますが、ノンインデックスキーを割り当てる方法や場所を正確にはわかりません。 (非インデックスは、ListViewが古い行と新しい行を比較するために使用するキーを意味します。データソースの配列のインデックスにのみ依存しません)
これらは私の質問です。
非インデックスキーを割り当てるにはどうすればよいですか?
インデックス以外のキーの割り当てに成功した場合、両方のケースですべての行を再レンダリングしない、前置き可能な追加可能なListViewを作成できますか?
もしそうでなければ、この問題をどのように解決していますか?これは非常に一般的な問題のように思えるので、ListViewにはまだこの機能がないことに非常に驚いています。
は*また、私はGitHubの上PrependableListViewを見てきましたが、それはListViewDataSourceの正確なコピーのように思える..私は何かが足りないのですか?私がPrependableListViewで見逃したことがあるなら、誰かがどこを指摘してくれますか?
私の問題を理解するために、私が使用しているテストコードを以下に示します。
/**
* Sample React Native App
* https://github.com/facebook/react-native
* @flow
*/
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
ListView,
RefreshControl,
View
} from 'react-native';
export default class Test1 extends Component {
constructor(props){
super(props);
const arr = [];
this.state = {
dataSource: new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}),
refreshing: false,
};
}
componentWillMount(){
this.arr = [];
for(let i = 0; i < 16; i++){
this.arr.push({keyy: i, data: "row " + i});
}
this.setState({
dataSource: this.state.dataSource.cloneWithRows(this.arr),
});
}
_onRefresh() {
this.setState({refreshing: true});
let i = this.arr.length;
let arr1 = [];
arr1.unshift({keyy: i, data: "row " + i});
for(var index = 0; index < this.arr.length; index++){
arr1.push(this.arr[index]);
}
// console.log(this.arr);
// console.log("arr1 : " + arr1.length);
this.setState({
dataSource: this.state.dataSource.cloneWithRows(arr1),
refreshing: false,
});
}
_renderRow(rowData: string, sectionID: number, rowID: number){
// console.log(rowData.data + " : " + sectionID + " : " + rowID);
return(
<Text style={{fontSize: 50}}>{rowData.data}</Text>
);
}
_onEndReached(){
let i = this.arr.length;
let arr1 = [];
for(var index = 0; index < this.arr.length; index++){
arr1.push(this.arr[index]);
}
arr1.push({keyy: i, data: "row " + i});
this.setState({
dataSource: this.state.dataSource.cloneWithRows(arr1),
});
}
render() {
return (
<ListView
dataSource={this.state.dataSource}
renderRow={this._renderRow.bind(this)}
refreshControl={
<RefreshControl
refreshing={this.state.refreshing}
onRefresh={this._onRefresh.bind(this)}
/>
}
onEndReachedThreshold={0}
onEndReached={this._onEndReached.bind(this)}
/>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('Test1',() => Test1);
あなたがコード内で見ることができるように、私は_onRefresh機能で行「unshifting」だ、と_onEndReached機能の行を「プッシュ」。これはうまくいくと思いますが、_onRefreshを完全に再描画してください。私が必要とするのは、私がシフトしていない、または押している行を再描画することだけです。
また、これが私の考え方です。
私は以下のように2 dataBlobsを比較.. 旧:[0,1,2,3,4,5] 新しい:[6,0,1,2,3,4,5]
ListView.DataSourceのデフォルトチェッカーは、デフォルトでdataBlob配列のインデックスとしてキー(またはRowID)を割り当てます。 (newsource.rowIdentities.push(Object.keys(dataBlob [sectionID])) 上記の場合、新しいdataBlobはキーとして[0,1,2,3,4,5,6]を持ち、 newDataBlob [sectionID] [0] - > 6!= 0 - >再描画 oldDataBlob [sectionID] [1] - > 0!newDataBlob [sectionID] [1] 1 - >再レンダリング oldDataBlob [sectionID] [2] - > 1!= 2 - >再レンダリング newDataBlob [sectionID] [3] newDataBlob [sectionID] [4] - > 3 - > 2 - > 3 - >再レンダリング newDataBlob [ 5]とoldDataBlob [sectionID] [5] - > 4!= 5 - >再レンダリング newDataBlob [セクションID] [6] oldDataBlob [セクションID] [6]と - > oldDataBlob [セクションID] [6]に定義されていない - >再レンダリング