FlatList renderItem被多次调用

时间:2018-07-16 16:01:17

标签: javascript react-native redux react-native-flatlist

我正在使用FlatList显示来自API调用的数据:

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)
}

返回的数据是一个包含3个对象和一个数组的数组,正如您在输出中看到的那样,该数组中的每个对象都会对一次renderItem()进行调用:

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

这是提取调用:

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);
    });
}

我发现了很多类似的帖子,他们说这是一个反应性的本机错误,我该怎么办?谢谢

编辑:

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);

但是现在的问题是滚动视图没有滚动。...

修改2: 我通过将所有return()内容包装在ScrollView中来解决此问题。-

2 个答案:

答案 0 :(得分:1)

正常重渲染在RN中是正常的。那只是RN更新反应树和更新视图。如果您没有性能问题,则可以忽略此问题。

否则,请解释问题,因为控制台日志很好。渲染项目针对传递给FlatList的数据数组中的每个项目执行。那就是每个项目的渲染功能,而不是整个列表的渲染功能。

如果这还不够清楚,并且对您来说更容易,请随时在此处用西班牙语添加评论,然后我们就可以更新答案(仅由您的用户这样说,因为您会说西班牙语,所以我会缝隙)

答案 1 :(得分:0)

https://snack.expo.io/B1KoX-EUN-为了优化和防止重新渲染,您可以调用shouldComponentUpdate(nextProps,nextState)来区分this.state或this.props并返回true / false-https://reactjs.org/docs/react-component.html#shouldcomponentupdate文档说此回调应仅用于优化,这就是我们在这里所做的。