update source react not horizontal flatlist extradata example code react-native react-native-listview

react-native - source - react native flatlist update



Reactivo-nativo FlatList no volver a presentar fila cuando cambian props (3)

El problema aquí radica en el hecho de que

  1. Está mutando un segmento de estado existente en lugar de crear una copia mutada

_onCategoryChosen = category => { var oldReportCopy = this.state.report; // This does not create a copy! oldReportCopy.selectedCategory = category; this.setState(Object.assign({}, this.state, { report: oldReportCopy })); };

Esto debería ser

_onCategoryChosen = category => { var oldReportCopy = Object.assign({}, this.state.report); oldReportCopy.selectedCategory = category; // setState handles partial updates just fine, no need to create a copy this.setState({ report: oldReportCopy }); };

  1. Las propiedades de FlatList siguen siendo las mismas, su función _renderRow puede basarse en la propiedad de categoría selectedCategory que cambia (si no es por el primer error), pero el componente FlatList no lo sabe. Para resolver esto, use el prop extraData .

    <FlatList data={this.props.items.categories.edges} renderItem={this._renderRow} horizontal={true} keyExtractor={(item, index) => item.node.id} extraData={this.props.selectedCategory} />

Tengo un problema con el nuevo componente FlatList. Específicamente, no redirige sus filas, aunque afirma que la fila depende de los cambios.

Los documentos de FlatList dicen que:

Este es un PureComponent, lo que significa que no se volverá a generar si los objetos permanecen igual de simples. Asegúrese de que todo de lo que depende su función renderItem se pasa como un elemento que no es === después de las actualizaciones, de lo contrario, es posible que su UI no se actualice en los cambios. Esto incluye la proposición de datos y el estado del componente principal.

LA PREGUNTA

Sin embargo, viendo que cambio un ID del elemento de categoría seleccionada - el elemento que debe indicar si la fila está ''seleccionada'' o no - creo que los elementos deben volver a enviarse. ¿Estoy equivocado?

Revisé los métodos ''componentWillReceiveProps'' tanto de la lista como de los componentes de la fila, y la lista recibe la actualización muy bien, pero el método del ciclo de vida de la fila nunca se llama.

Si incluyo un valor de estado booleano aleatorio e inútil en el componente de lista, y lo cambio de un lado a otro cuando se actualicen los accesorios, funciona, pero no sé por qué.

state = { updated: false }; componentWillReceiveProps(nextProps) { this.setState(oldstate => ({ updated: !oldstate.updated, })); } <FlatList data={this.props.items.allAnimalCategories.edges} renderItem={this._renderRow} horizontal={true} keyExtractor={(item, index) => item.node.id} randomUpdateProp={this.state.updated} />

EL CÓDIGO

La estructura de mi código es la siguiente: tengo un componente contenedor con toda la lógica y el estado, que contiene un componente FlatList (presentación, sin estado), que a su vez contiene una fila de presentación personalizada.

Container Custom list component that includes the FlatList component (presentational, stateless) and the renderRow method Custom row (presentational, stateless)

El contenedor incluye este componente:

<CustomList items={this.props.viewer} onCategoryChosen={this._onCategoryChosen} selectedCategory={this.state.report.selectedCategory} />

Lista personalizada:

class CustomList extends Component { _renderRow = ({ item }) => { return ( <CustomListRow item={item.node} selectedCategory={this.props.selectedCategory} onPressItem={this.props.onCategoryChosen} /> ); }; render() { return ( <View style={_styles.container}> <FlatList data={this.props.items.categories.edges} renderItem={this._renderRow} horizontal={true} keyExtractor={(item, index) => item.node.id} randomUpdateProp={this.state.updated} /> </View> ); }

}

(Los datos provienen de Relay)

Finalmente la fila:

render() { const idsMatch = this.props.selectedCategory.id == this.props.item.id; return ( <TouchableHighlight onPress={this._onItemPressed}> <View style={_styles.root}> <View style={[ _styles.container, { backgroundColor: this._getBackgroundColor() }, ]}> {idsMatch && <Image style={_styles.icon} source={require(''./../../res/img/asd.png'')} />} {!idsMatch && <Image style={_styles.icon} source={require(''./../../res/img/dsa.png'')} />} <Text style={_styles.text}> {capitalizeFirstLetter(this.props.item.name)} </Text> </View> <View style={_styles.bottomView}> <View style={_styles.greyLine} /> </View> </View> </TouchableHighlight> ); }

La fila no es tan interesante, pero la incluí para mostrar que es completamente apátrida y depende de los apoyos de sus padres.

El estado se actualiza así:

_onCategoryChosen = category => { var oldReportCopy = this.state.report; oldReportCopy.selectedCategory = category; this.setState(Object.assign({}, this.state, { report: oldReportCopy })); };

Estado se ve así:

state = { ... report: defaultStateReport, }; const defaultStateReport = { selectedCategory: { id: ''some-long-od'', name: '''', }, ... };


Estoy de acuerdo con Nimelrian. Además, si su estado es una matriz, puede crear un objeto de matriz a partir del estado haciendo lo siguiente:

var oldReportCopy = Object.assign([], this.state.report);

Luego use el método .push () para agregarle su nuevo objeto de esta manera:

oldReportCopy.push(selectedCategory);

A continuación, puede volver a establecer este nuevo objeto de matriz en el estado:

this.setState({ report: oldReportCopy });


Simplemente puede resolver este problema pasando los accesorios a extraData en un componente de lista plana como este,

<FlatList data={this.props.data} extraData={this.props} keyExtractor={this._keyExtractor} renderItem={this._renderItem} />