usando React.memo en el componente funcional para renderItem FlatList para minimizar volver a renderizar elementos existentes

Aug 20 2020

Estoy usando componentes funcionales y usando Flatlist para representar la lista de datos, funciona bien, pero cada vez que el estado obtiene datos adicionales, siempre vuelve a representar los existentes y causará problemas de rendimiento. He leído estos artículos de SO pero todavía tengo sin pistas

  • https://stackoverflow.com/a/57405307/938947
  • https://stackoverflow.com/a/46349156/938947

aquí está mi código que usa Flatlist principal

<FlatList
  horizontal={false}
  showsHorizontalScrollIndicator={false}
  data={users}
  keyExtractor={(item, index) => String(index)}
  renderItem={RenderUser}
  onEndReachedThreshold={0.7}
  onEndReached={callBackMoreData}
/>

y aquí está trabajando RenderUser pero el problema es volver a renderizar el elemento existente si el estado tiene datos adicionales, lo que me gustaría lograr es solo renderizar datos adicionales

import React from 'react';
import { ListItem } from 'react-native-elements';

const RenderUser = ({ item, index }) => {

  return (
    <React.Fragment>
      { console.log('index: ', index)}
      <ListItem 
        title={item.attributes.name}
      />
    </React.Fragment>
  );
};

export default RenderUser;

y traté de usar este código a continuación (pero recibo un mensaje de error que dice TypeError: renderItem no es una función. (en 'renderItem (props)', 'renderItem' es una instancia de objeto))

import React, { memo } from 'react';
import { ListItem } from 'react-native-elements';

const RenderUser = ({ item, index }) => {

  return (
    <React.Fragment>
      { console.log('index: ', index)}
      <ListItem 
        title={item.attributes.name}
      />
    </React.Fragment>
  );
};

export default memo(RenderUser);

Respuestas

2 ShubhamVerma Aug 20 2020 at 15:18

De acuerdo con la documentación oficial de reacción:

Por defecto, solo comparará superficialmente objetos complejos en el objeto props. Si desea controlar la comparación, también puede proporcionar una función de comparación personalizada como segundo argumento.

function MyComponent(props) {
  /* render using props */
}
function areEqual(prevProps, nextProps) {
  /*
  return true if passing nextProps to render would return
  the same result as passing prevProps to render,
  otherwise return false
  */
}
export default React.memo(MyComponent, areEqual);

En su caso, debe agregar la condición:

import React, { memo } from 'react';
import { ListItem } from 'react-native-elements';

const RenderUser = ({ item, index }) => {

  return (
    <React.Fragment>
      { console.log('index: ', index)}
      <ListItem 
        title={item.attributes.name}
      />
    </React.Fragment>
  );
};

function arePropsEqual(prevProps, nextProps) {
      /*
      return true if passing nextProps to render would return
      the same result as passing prevProps to render,
      otherwise return false
      */
      return nextProps.item.attribute.name===prevProps.item.attribute.name
    }

export default memo(RenderUser,arePropsEqual);

Nota : No estoy seguro de cuántos accesorios está recibiendo y cuáles son únicos. Básicamente, debe comparar que el último es igual a este, devolver verdadero de esa manera, reaccionar no vuelve a renderizar su componente