¿Cómo volver a renderizar la lista plana?


86

A diferencia de ListView, podemos actualizar this.state.datasource. ¿Existe algún método o ejemplo para actualizar FlatList o volver a renderizarlo?

Mi objetivo es actualizar el valor del texto cuando el usuario presiona el botón ...

renderEntries({ item, index }) {
    return(
        <TouchableHighlight onPress={()=> this.setState({value: this.state.data[index].value+1})>
             <Text>{this.state.data[index].value}</Text>
        </TouchableHighlight>
    )
}

<FlatList 
    ref={(ref) => { this.list = ref; }} 
    keyExtractor={(item) => item.entry.entryId} 
    data={this.state.data} 
    renderItem={this.renderEntries.bind(this)} 
    horizontal={false} />

7
Los documentos de FlatList dicen "Esto es un lo PureComponentque significa que no se volverá a renderizar si los accesorios permanecen poco profundos, iguales. Asegúrese de que todo lo que renderItemdepende de su función se pase como un accesorio que no sea ===posterior a las actualizaciones, de lo contrario, es posible que su interfaz de usuario no se actualice sobre cambios. Esto incluye el dataestado del componente principal y de prop. " ¿Estás siguiendo este consejo?
Jordan Running

3
No importa con lo que intenté extraDatay shouldItemUpdate, no pude volver a renderizar la lista. Lo que terminé haciendo fue borrar el estado, esperar a que se procesara y luego actualizar el estado. this.setState({ data: null }, () => { this.setState({ data: actualData }) });
Joshua Pinter

Respuestas:


186

Utilizar el extraData propiedad en su componente FlatList.

Como dice la documentación:

Al pasar extraData={this.state}a FlatListnos aseguramos de que FlatListse volverá a renderizar cuando los state.selectedcambios. Sin establecer este accesorio, FlatListno sabría que necesita volver a renderizar ningún elemento porque también es un PureComponenty la comparación de accesorios no mostrará ningún cambio.


34
Estoy usando redux y, en ese caso, estoy enviando datos como data={this.props.searchBookResults}y ni extraData={this.state}tampoco extraData={this.props}funcionan para mí. Y data={this.props.searchBookResults}tampoco está funcionando. Qué hacer ?
Sujit el

8
Use extraData: para actualizar su <FlatList>... data={this.props.searchBookResults} extraData={this.state.refresh} onPress={()={this.setState({ refresh: !refresh})}
No,

9
Estoy luchando con el mismo problema. No importa lo que transmita extraData, el componente no se actualiza :(
Denis Cappelini

2
@DenisCappelini, asegúrese de que los datos pasados ​​a la extraDatapropiedad cambien cuando los elementos secundarios deben volver a procesarse. Por ejemplo, si los elementos de la lista pueden estar activos / inactivos, asegúrese de que la variable de estado, ya sea parte del this.stateobjeto o del this.propsobjeto, sea lo que debe entrar extraData. Puede ser un cursor o una serie de elementos activos, etc.
Emperor_Earth

1
@Sujit Me estaba encontrando con el mismo problema, pero luego me di cuenta de que había implementado shouldComponentUpdate(), una vez que actualicé eso o lo comenté por completo, las cosas estaban funcionando tal como se describe en la documentación.
JanithaR

51

Para una solución rápida y sencilla Pruebe:

  1. establecer datos adicionales en un valor booleano.

    extraData = {this.state.refresh}

  2. Cambie el valor del estado booleano cuando desee volver a renderizar / actualizar la lista

    this.setState({ 
        refresh: !this.state.refresh
    })
    

Eso es exactamente lo que necesito ya que agregaré datos al soporte de datos. Además, esa es una implementación súper extraña del equipo de React-Native ... tendría mucho más sentido tener una función o propiedad de actualización en los datos. IE: this.data.refresh(). En su lugar, establecemos un valor booleano y lo cambiamos. El valor booleano en sí no tiene significado, entonces, ¿cuál es el punto de que exista? ... (No tiene sentido, aparte de hacer que los datos se actualicen, ¿verdad?)
YungGun

@HradeshKumar Lo hago, ¡pero el último elemento dentro de Data no puede desaparecer!
DevAS

esto funciona de maravilla, pero todavía no sé por qué this.state.usersno estaba funcionando, a pesar de que estaba cambiando una bandera en algunos usuarios.
shyammakwana.me

21

Oh, eso es fácil, solo usa extraData

Verá que la forma en que funcionan los datos adicionales detrás de escena es FlatList o VirtualisedList simplemente verifica si ese objeto ha cambiado a través de unonComponentWillReceiveProps método .

Así que todo lo que tienes que hacer es asegurarte de dar algo que cambie al extraData .

Esto es lo que hago:

Estoy usando immutable.js, así que todo lo que hago es pasar un mapa (objeto inmutable) que contiene lo que quiero ver.

<FlatList
    data={this.state.calendarMonths}
    extraData={Map({
        foo: this.props.foo,
        bar: this.props.bar
    })}
    renderItem={({ item })=>((
        <CustomComponentRow
            item={item}
            foo={this.props.foo}
            bar={this.props.bar}
        />
    ))}
/>

De esa forma, cuando this.props.fooo this.props.barcambie, nuestro CustomComponentRowse actualizará, porque el objeto inmutable será diferente al anterior.


2
finalmente entendí extraData! gracias por el enlace al VirtualisedListcódigo!
Tushar Koul

hola, @ SudoPiz Quiero volver a renderizar Flatlist después de eliminar el último elemento, puedo consultar esta Q stackoverflow.com/questions/58780167/…
Oliver D

6

OK, acabo de descubrir que si queremos que FlatList sepa el cambio de datos fuera del soporte de datos, necesitamos configurarlo en extraData, así que lo hago así ahora:

<FlatList data={...} extraData={this.state} .../>

consulte: https://facebook.github.io/react-native/docs/flatlist#extradata


1
La mejor implementación ... Preferí configurarlo como el mismo que el accesorio de datos, por lo que no se actualiza cuando cambia algo en el estado, pero esta es la implementación MÁS FÁCIL con diferencia. ¡Gracias!
Robert Kehoe

hola, @MahdiBashirpour Quiero volver a renderizar Flatlist después de eliminar el último elemento, puedo consultar esta Q stackoverflow.com/questions/58780167/…
Oliver D

4

Si va a tener un Button, puede actualizar los datos con un setState dentro de onPress. SetState luego volverá a renderizar su FlatList.


2
hay un setState en mi touchhighlight. el setState funciona bien pero la lista plana no muestra la actualización del valor del estado -> this.state.value
shalonteoh

Los valores en su FlastList no se actualizan porque no está actualizando la fuente de datos directamente. this.state.data es lo que se representa con FlatList, pero en onPress solo está actualizando this.state.value.
WilliamC

perdón mi error, error tipográfico en la pregunta. debería ser this.state.data [index] .value
shalonteoh

3

Después de mucho buscar y buscar una respuesta real, finalmente obtuve la respuesta que creo que es la mejor:

       <FlatList
      data={this.state.data}
      renderItem={this.renderItem}
      ListHeaderComponent={this.renderHeader}
      ListFooterComponent={this.renderFooter}
      ItemSeparatorComponent={this.renderSeparator}
      refreshing={this.state.refreshing}
      onRefresh={this.handleRefresh}
      onEndReached={this.handleLoadMore}
      onEndReachedThreshold={1}
      extraData={this.state.data}
      removeClippedSubviews={true}
      **keyExtractor={ (item, index) => index }**
              />
    .....

mi principal problema era (KeyExtractor) no lo estaba usando así. no funciona: keyExtractor = {(item) => item.ID} después de que cambié a esto funcionó como un encanto, espero que esto ayude a alguien.


¿Puedes poner el valor de this.state.refreshingy la función handleRefresh?
DevAS

1

Resolví este problema agregando extraData={this.state}Verifique el código a continuación para obtener más detalles

render() {
    return (
      <View style={styles.container}>
        <FlatList
          data={this.state.arr}
          extraData={this.state}
          renderItem={({ item }) => <Text style={styles.item}>{item}</Text>}
        />
      </View>
    );
  }

1

Solo una extensión de las respuestas anteriores aquí. Dos partes para asegurarse, asegúrese de agregar extraData y que su keyExtractor sea único. Si su keyExtractor es constante, no se activará una repetición.

<FlatList
data={this.state.AllArray}
extraData={this.state.refresh}
renderItem={({ item,index })=>this.renderPhoto(item,index)}
keyExtractor={item => item.id}
>
                                    </FlatList>

0

He substituido FlatListcon SectionListy está actualizaciones correctamente en cambio de estado.

<SectionList
  keyExtractor={(item) => item.entry.entryId} 
  sections={section}
  renderItem={this.renderEntries.bind(this)}
  renderSectionHeader={() => null}
/>

Lo único que hay que tener en cuenta es que sectiontienen estructura de diferencias:

const section = [{
  id: 0,
  data: this.state.data,
}]

0

Para mí, el truco fue extraData y profundizar en el componente del elemento una vez más

state = {
  uniqueValue: 0
}

<FlatList
  keyExtractor={(item, index) => item + index}
  data={this.props.photos}
  renderItem={this.renderItem}
  ItemSeparatorComponent={this.renderSeparator}
/>

renderItem = (item) => {
  if(item.item.selected) {
    return ( <Button onPress={this.itemPressed.bind(this, item)}>Selected</Button> );
  }
  return ( <Button onPress={this.itemPressed.bind(this, item)}>Not selected</Button>);
}

itemPressed (item) {
  this.props.photos.map((img, i) => {
    if(i === item.index) {
      if(img['selected') {
        delete img.selected;
      } else {
        img['selected'] = true;
      }
      this.setState({ uniqueValue: this.state.uniqueValue +1 });
    }
  }
}

0

Coloque las variables que cambiará su interacción en extraData

Puedes ser creativo.

Por ejemplo, si se trata de una lista cambiante con casillas de verificación.

<FlatList
      data={this.state.data.items}
      extraData={this.state.data.items.length * (this.state.data.done.length + 1) }
      renderItem={({item}) => <View>  

0

Si queremos que FlatList sepa que los datos cambian tanto en la propiedad como en el estado , podemos construir un objeto que haga referencia tanto a la propiedad como al estado y actualizar la lista plana.

const hasPropOrStateChange = { propKeyToWatch: this.props, ...this.state};
<FlatList data={...} extraData={this.hasPropOrStateChange} .../>

Documentos: https://facebook.github.io/react-native/docs/flatlist#extradata


0

En react-native-flatlist, son una propiedad llamada extraData. agregue la siguiente línea a su lista plana.

 <FlatList
          data={data }
          style={FlatListstyles}
          extraData={this.state}
          renderItem={this._renderItem}
       />

0

En este ejemplo, para forzar una repetición, simplemente cambie la variable machine

const [selected, setSelected] = useState(machine)

useEffect(() => {
    setSelected(machine)
}, [machine])


-1

El extraData de Flatlist no funcionaba para mí y estaba usando un accesorio de redux. Esto sonó similar a los problemas de los comentarios en la respuesta de ED209. Terminé llamando manualmente a setState cuando recibí el prop.

componentWillReceiveProps(nextProps: StateProps) {
    if (this.props.yourProp != null && nextProps.yourProp) {
        this.setState({ yourState: processProp(nextProps.yourProp) });
    }
}


<FlatList
  data={this.state.yourState}
  extraData={this.state.yourState}
/>

Para aquellos de ustedes que usan> React 17, use getDerivedStateFromProps

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.