style react flatlist example javascript ios arrays datasource react-native

javascript - flatlist - React-Native Actualización de la vista de lista DataSource



listitem react native elements style (3)

En caso de que alguien se encuentre con este problema como yo, aquí está la solución completa.

Básicamente, parece que hay un error con el componente ListView y necesita reconstruir cada elemento que cambia en el origen de datos para que ListView lo vuelva a dibujar.

Aquí hay un ejemplo de trabajo: https://rnplay.org/apps/GWoFWg

Primero, cree la fuente de datos y una copia de la matriz y guárdelos en el estado. En mi caso, los foods son la matriz.

constructor(props){ super(props); var ds = new ListView.DataSource({ rowHasChanged: (row1, row2) => row1 !== row2, }); this.state = { dataSource: ds.cloneWithRows(foods), db: foods, }; }

Cuando desee cambiar algo en la fuente de datos, haga una copia de la matriz que guardó en el estado, reconstruya el elemento con el cambio y luego guarde la nueva matriz con el cambio de nuevo al estado (tanto db como datasource).

onCollapse(rowID: number) { console.log("rowID", rowID); var newArray = this.state.db.slice(); newArray[rowID] = { key: newArray[rowID].key, details: newArray[rowID].details, isCollapsed: newArray[rowID].isCollapsed == false ? true : false, }; this.setState({ dataSource: this.state.dataSource.cloneWithRows(newArray), db: newArray, }); }

Tengo una aplicación de iOS que estoy haciendo con react-native. La clase Game contiene un componente ListView. Establecí el estado en el constructor e dataSource un dataSource . Tengo una matriz de datos codificados por ahora que this.state.ds en una propiedad de estado diferente ( this.state.ds ). Luego en el componentDidMount utilizo el método cloneWithRows para clonar my this.state.ds como mi dataSource para la vista. Eso es bastante estándar en lo que respecta a ListViews y funciona bien. Aquí está el código:

/** * Sample React Native App * https://github.com/facebook/react-native */ ''use strict''; var React = require(''react-native''); var { StyleSheet, Text, View, ListView, TouchableHighlight } = React; class Games extends React.Component{ constructor(props){ super(props); var ds = new ListView.DataSource({ rowHasChanged: (r1, r2) => r1 != r2 }); this.state = { ds:[{AwayTeam: "TeamA", HomeTeam: "TeamB", Selection: "AwayTeam"},{AwayTeam: "TeamC", HomeTeam: "TeamD", Selection: "HomeTeam"}], dataSource:ds, } } componentDidMount(){ this.setState({ dataSource:this.state.dataSource.cloneWithRows(this.state.ds), }) } pressRow(rowData){ var newDs = []; newDs = this.state.ds; newDs[0].Selection = newDs[0] == "AwayTeam" ? "HomeTeam" : "AwayTeam"; this.setState({ dataSource: this.state.dataSource.cloneWithRows(newDs) }) } renderRow(rowData){ return ( <TouchableHighlight onPress={()=> this.pressRow(rowData)} underlayColor = ''#ddd''> <View style ={styles.row}> <Text style={{fontSize:18}}>{rowData.AwayTeam} @ {rowData.HomeTeam} </Text> <View style={{flex:1}}> <Text style={styles.selectionText}>{rowData[rowData.Selection]}</Text> </View> </View> </TouchableHighlight> ) } render(){ return ( <ListView dataSource = {this.state.dataSource} renderRow = {this.renderRow.bind(this)}> </ListView> ); } } var styles = StyleSheet.create({ row:{ flex:1, flexDirection:''row'', padding:18, borderBottomWidth: 1, borderColor: ''#d7d7d7'', }, selectionText:{ fontSize:15, paddingTop:3, color:''#b5b5b5'', textAlign:''right'' }, }); module.exports = Games

El problema que estoy teniendo viene en el método pressRow . Cuando el usuario presiona la fila, me gustaría que la selección cambie y que muestre el cambio en el dispositivo. A través de algunas depuraciones, he notado que aunque estoy cambiando la propiedad Selection del objeto en la matriz newDs , la misma propiedad cambia en el objeto en this.state.ds y de manera similar cambia el objeto en this.state.dataSource._dataBlob.s1 . Mediante una mayor depuración, he descubierto que, dado que esas otras matrices han cambiado, el objeto DataSource de ListView no reconoce el cambio porque cuando establezco el estado y se llama a rowHasChanged , la matriz que this.state.dataSource._dataBlob.s1 coincide con la matriz this.state.dataSource._dataBlob.s1 y por lo tanto no se ve como un cambio y no se renueva.

¿Algunas ideas?


Prueba esto:

pressRow(rowData){ var newDs = []; newDs = this.state.ds.slice(); newDs[0].Selection = newDs[0] == "AwayTeam" ? "HomeTeam" : "AwayTeam"; this.setState({ dataSource: this.state.dataSource.cloneWithRows(newDs) }) }

Esto debería hacer una copia de la matriz, que luego se puede modificar independientemente de la matriz original en this.state.ds .


reaccionar es lo suficientemente inteligente como para detectar cambios en dataSource y si la lista debe volver a procesarse. Si desea actualizar listView, cree nuevos objetos en lugar de actualizar las propiedades de los objetos existentes. El código se vería así:

let newArray = this._rows.slice(); newArray[rowID] = { ...this._rows[rowID], Selection: !this._rows[rowID].Selection, }; this._rows = newArray; let newDataSource = this.ds.cloneWithRows(newArray); this.setState({ dataSource: newDataSource });

Puede leer más sobre un problema similar en Github