FlatList renderItem is called multiple times

柔情痞子 提交于 2019-11-26 14:57:46

问题


I'm using FlatList to display data from an API call:

render() {
  const { navigation } = this.props;
  const animating = this.state.animating;

  return (
    <View style={styles.container}>
      <ActivityIndicator
        animating = {animating}
        color = '#E3A141'
        size = {120}
        style = {styles.activityIndicator}
      /> 
      <FlatList                    
        ref='listRef'
        data={this.props.data}
        renderItem={this.renderItem}
        keyExtractor={(item, index) => index.toString()}
      />   
      <SocialFooter navigation={navigation}/>
    </View>
  )
}

renderItem({item, index}) {
  console.log("renderItem(item): ", item, "index: ", index)
}

The returned data is an array with 3 objects and an array, as you can see in the output renderItem() is called once per object in the array:

renderItem(item):  Object {
12:47:38:   "antiparasitario": "SI",
12:47:38:   "color": "BLANCO",
12:47:38:   "contrato": "00345",
12:47:38:   "datoCobol": 1,
12:47:38:   "dtomedicamentos": "SI",
12:47:38:   "dtovacunas": "SI",
12:47:38:   "especie": "01",
12:47:38:   "extraccsangre": "NO",
12:47:38:   "fecnac": "2013-05-01",
12:47:38:   "hayPendientes": 0,
12:47:38:   "nombre": "ASTOR",
12:47:38:   "orden": "01",
12:47:38:   "ordenLocal": "01",
12:47:38:   "peso": "030.000",
12:47:38:   "raza": 107,
12:47:38:   "rutafoto": "",
12:47:38:   "sexo": "M",
12:47:38:   "sociode": "MASCOTA24",
12:47:38:   "traslado": "SI",
12:47:38: } index:  0
12:47:39: renderItem(item):  Object {
12:47:39:   "antiparasitario": "SI",
12:47:39:   "color": "BALNCO",
12:47:39:   "contrato": "00345",
12:47:39:   "datoCobol": 1,
12:47:39:   "dtomedicamentos": "SI",
12:47:39:   "dtovacunas": "SI",
12:47:39:   "especie": "01",
12:47:39:   "extraccsangre": "NO",
12:47:39:   "fecnac": "2017-05-01",
12:47:39:   "hayPendientes": 0,
12:47:39:   "nombre": "APACHE",
12:47:39:   "orden": "02",
12:47:39:   "ordenLocal": "02",
12:47:39:   "peso": "025.000",
12:47:39:   "raza": 107,
12:47:39:   "rutafoto": "",
12:47:39:   "sexo": "M",
12:47:39:   "sociode": "MASCOTA24",
12:47:39:   "traslado": "SI",
12:47:39: } index:  1
12:47:39: renderItem(item):  Object {
12:47:39:   "antiparasitario": "SI",
12:47:39:   "color": "MARRON",
12:47:39:   "contrato": "00345",
12:47:39:   "datoCobol": 1,
12:47:39:   "dtomedicamentos": "SI",
12:47:39:   "dtovacunas": "SI",
12:47:39:   "especie": "01",
12:47:39:   "extraccsangre": "NO",
12:47:39:   "fecnac": "2015-05-01",
12:47:39:   "hayPendientes": 0,
12:47:39:   "nombre": "CORA",
12:47:39:   "orden": "03",
12:47:39:   "ordenLocal": "03",
12:47:39:   "peso": "005.000",
12:47:39:   "raza": 43,
12:47:39:   "rutafoto": "",
12:47:39:   "sexo": "H",
12:47:39:   "sociode": "MASCOTA24",
12:47:39:   "traslado": "SI",
12:47:39: } index:  2
12:47:39: renderItem(item):  Array [
12:47:39:   Object {
12:47:39:     "dni": "0303456",
12:47:39:     "socioID": 2020,
12:47:39:     "titular": "Jonny Melaslavo",
12:47:39:   },
12:47:39: ] index:  3
12:47:39: renderItem(item):  Object {
12:47:39:   "antiparasitario": "SI",
12:47:39:   "color": "BLANCO",
12:47:39:   "contrato": "00345",
12:47:39:   "datoCobol": 1,
12:47:39:   "dtomedicamentos": "SI",
12:47:39:   "dtovacunas": "SI",
12:47:39:   "especie": "01",
12:47:39:   "extraccsangre": "NO",
12:47:39:   "fecnac": "2013-05-01",
12:47:39:   "hayPendientes": 0,
12:47:39:   "nombre": "ASTOR",
12:47:39:   "orden": "01",
12:47:39:   "ordenLocal": "01",
12:47:39:   "peso": "030.000",
12:47:39:   "raza": 107,
12:47:39:   "ruta_img": 3,
12:47:39:   "rutafoto": "",
12:47:39:   "sexo": "M",
12:47:39:   "sociode": "MASCOTA24",
12:47:39:   "traslado": "SI",
12:47:39: } index:  0
12:47:39: renderItem(item):  Object {
12:47:39:   "antiparasitario": "SI",
12:47:39:   "color": "BALNCO",
12:47:39:   "contrato": "00345",
12:47:39:   "datoCobol": 1,
12:47:39:   "dtomedicamentos": "SI",
12:47:39:   "dtovacunas": "SI",
12:47:39:   "especie": "01",
12:47:39:   "extraccsangre": "NO",
12:47:39:   "fecnac": "2017-05-01",
12:47:39:   "hayPendientes": 0,
12:47:39:   "nombre": "APACHE",
12:47:39:   "orden": "02",
12:47:39:   "ordenLocal": "02",
12:47:39:   "peso": "025.000",
12:47:39:   "raza": 107,
12:47:39:   "ruta_img": 3,
12:47:39:   "rutafoto": "",
12:47:39:   "sexo": "M",
12:47:39:   "sociode": "MASCOTA24",
12:47:39:   "traslado": "SI",
12:47:39: } index:  1
12:47:39: renderItem(item):  Object {
12:47:39:   "antiparasitario": "SI",
12:47:39:   "color": "MARRON",
12:47:39:   "contrato": "00345",
12:47:39:   "datoCobol": 1,
12:47:39:   "dtomedicamentos": "SI",
12:47:39:   "dtovacunas": "SI",
12:47:39:   "especie": "01",
12:47:39:   "extraccsangre": "NO",
12:47:39:   "fecnac": "2015-05-01",
12:47:39:   "hayPendientes": 0,
12:47:39:   "nombre": "CORA",
12:47:39:   "orden": "03",
12:47:39:   "ordenLocal": "03",
12:47:39:   "peso": "005.000",
12:47:39:   "raza": 43,
12:47:39:   "ruta_img": 3,
12:47:39:   "rutafoto": "",
12:47:39:   "sexo": "H",
12:47:39:   "sociode": "MASCOTA24",
12:47:39:   "traslado": "SI",
12:47:39: } index:  2
12:47:39: renderItem(item):  Array [
12:47:39:   Object {
12:47:39:     "dni": "0303456",
12:47:39:     "socioID": 2020,
12:47:39:     "titular": "Jonny Melaslavo",
12:47:39:   },
12:47:39: ] index:  3

This is the fetch call:

function makeDataRequest(token, nro_socio) {
  let datos_socio = [];
  fetch('http://www.api/' + nro_socio, {
      method: 'GET',
      headers: {
        'Content-Type': 'application/json',
        'token': token
      },
    }).then((response) => response.json())
    .then((responseJson) => {
      if (responseJson.errores) {
        dispatch({
          type: DATA_AVAILABLE,
          data: ['sin_serv_vet']
        });
      } else {
        let responseObj = responseJson.mascotas;
        if (responseObj == '') {
          dispatch({
            type: DATA_AVAILABLE,
            data: ['sin_mascotas']
          });
        }
        datos_socio.push({
          titular: responseJson.titular,
          dni: responseJson.doc,
          socioID: nro_socio
        });
        responseObj.push(datos_socio);
        dispatch({
          type: DATA_AVAILABLE,
          data: responseObj
        });
      }
    })
    .catch((error) => {
      console.error(error);
    });
}

I've found lots of similar posts and they say is a react native bug, what can i do?. Thanks

Edit:

class UserPage extends Component {

    static navigationOptions = { header: null }

    constructor(props) {
        super(props);
        this.state = {
            animating: true,
            isModalVisible: false
        };
        dni = props.match.params.username;           
        this.props.getData(dni);
        this.renderItem = this.renderItem.bind(this);
    }

    componentWillReceiveProps(nextProps) {             
        this.closeActivityIndicator();
        if (nextProps.data == "dni_incorrecto") {
            this.props.history.push('/'+"dni_incorrecto");
        } else if (nextProps.data == "sin_serv_vet") {
            this.props.history.push('/'+"sin_serv_vet");
        } else if (nextProps.data == "sin_mascotas") {
            this.props.history.push('/'+"sin_mascotas");
        }
    }

    closeActivityIndicator() {
        this.setState({ 
            animating: false 
        })
    }

    render() {
        return null;
        console.log("data length: ", this.props.data.length);
        if (this.props.data.length) { 
            const datosSocio = this.props.data[0].datos_socio;

            return ( 
                <View>
                    <View style={styles.header_container}>
                        <Image source={require('./img/logo-mini.png')} style={styles.logo_img} />
                        <Link to="/" style={styles.back_link} underlayColor="#f0f4f7">
                            <Image  
                                source={require("./img/back.png")}
                                style={styles.back_img}
                            />
                        </Link>
                    </View>
                    <View style={styles.container_credential}>
                        <Image source={require('./img/base-face-image.png')} style={styles.customer_img} />
                        <View style={styles.credential_details}>
                            <Text style={styles.customer_fullName}>
                                {datosSocio.titular} 
                            </Text>
                            <Text style={styles.customer_member_id}>
                                Socio ID: {datosSocio.socioID}                         
                            </Text>
                            <Text style={styles.customer_dni}>
                                DNI: {datosSocio.dni}                
                            </Text>
                            <Text style={styles.credential_notice_title}>
                                ¡IMPORTANTE! 
                            </Text>
                            <Text style={styles.credential_notice_content}>
                                El uso de esta credencial debe ser acompañado por el DNI del titular.
                            </Text>
                        </View>
                    </View>
                    <View style={styles.container_mascotas_list_title}> 
                        <Text style={styles.mascotas_list_title_text_first}>Mis</Text><Text style={styles.mascotas_list_title_text_last}> mascotas:</Text>                    
                    </View>
                    <View style={styles.mascotas_list_title_underline}></View>
                    <ScrollView>          
                        {this.props.data.map(mascota => {
                            return ( 
                            <View key={mascota.nombre}>

                                    <Text style={styles.mascotas_list_item_details_name}>Nombre: {mascota.nombre}</Text>                                    
                                    <Text style={styles.mascotas_list_item_details_name}>Raza: {getRaza(mascota.raza)}</Text>
                                    <Text style={styles.mascotas_list_item_details_name}>Especie: {getEspecie(mascota.raza)}</Text>
                                    <Text style={styles.mascotas_list_item_details_sex_hair}>Sexo: {mascota.sexo}</Text>
                                    <Text style={styles.mascotas_list_item_details_sex_hair}>Color pelo: {mascota.color}</Text>

                            </View>
                            );
                        })}
                    </ScrollView>
                </View>
          );
        } else {
          return null;
        }
      }
};

function getRaza(id_raza) {
    for (let i = 0; i < razas.length; i++) {
        if (razas[i][0] == id_raza) {
            return razas[i][1];
        }
    }
}

function getEspecie(id_raza) {
    for (let i = 0; i < razas.length; i++) {         
        if (razas[i][0] == id_raza) {
            return razas[i][2];
        }
    }
}

// The function takes data from the app current state,
// and insert/links it into the props of our component.
// This function makes Redux know that this component needs to be passed a piece of the state
function mapStateToProps(state, props) {
    return {
        loading: state.dataReducer.loading,
        data: state.dataReducer.data
    }
}

// Doing this merges our actions into the component’s props,
// while wrapping them in dispatch() so that they immediately dispatch an Action.
// Just by doing this, we will have access to the actions defined in out actions file (action/home.js)
function mapDispatchToProps(dispatch) {
    return bindActionCreators(Actions, dispatch);
}

//Connect everything
export default connect(mapStateToProps, mapDispatchToProps)(UserPage);

However now the problem is that the scrollview is not scrolling....

Edit 2: I resolved this by wrapping all the return() content inside ScrollView.-


回答1:


Normal re renders are normal in RN. That is just RN updating the react tree and updating views. If you dont have a performance issue then you can ignore this.

Otherwise, please explain the problem because the console log is fine. Render item executes for EACH item in the data array you pass to FlatList. That is the render function for each item, not the render for the whole list.

If this is not clear enough, and it is easier for you, feel free to add here a comment in Spanish and then we can update the answer (Only saying this since by your user, you seam spanish speaker as I am)




回答2:


https://snack.expo.io/B1KoX-EUN - For optimization and prevent re-render you can call shouldComponentUpdate(nextProps, nextState) to diff this.state or this.props and return true/false - https://reactjs.org/docs/react-component.html#shouldcomponentupdate docs say this callback should be used only for optimization which is what we're doing here.



来源:https://stackoverflow.com/questions/51365912/flatlist-renderitem-is-called-multiple-times

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!