использование React.memo в функциональном компоненте для renderItem FlatList для минимизации повторного рендеринга существующих элементов

Aug 20 2020

Я использую функциональные компоненты и использую Flatlist для рендеринга списка данных, он работает нормально, но каждый раз, когда состояние получает дополнительные данные, он всегда повторно отображает существующие, и это вызовет проблемы с производительностью, я прочитал эти статьи из SO, но все еще имеет нет подсказок

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

вот мой код, использующий основной Flatlist

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

и здесь работает RenderUser, но проблема в том, что он повторно отображает существующий элемент, если в состоянии есть дополнительные данные, я бы хотел достичь только визуализации дополнительных данных

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;

и я попытался использовать этот код ниже (но я получаю сообщение об ошибке, в котором говорится, что TypeError: renderItem не является функцией. (в 'renderItem (props)', 'renderItem' является экземпляром объекта))

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

Ответы

2 ShubhamVerma Aug 20 2020 at 15:18

Согласно официальной документации:

По умолчанию он будет только поверхностно сравнивать сложные объекты в объекте props. Если вы хотите контролировать сравнение, вы также можете предоставить настраиваемую функцию сравнения в качестве второго аргумента.

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

В вашем случае вам нужно добавить условие:

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

Примечание . Не уверен, сколько реквизитов вы получаете и какие уникальные. В основном вам нужно сравнить, что последний равен этому возвращению true, таким образом, реакция не будет повторно отображать ваш компонент