機能コンポーネントでReact.memoを使用してRenderItemFlatListを使用し、既存のアイテムの再レンダリングを最小限に抑えます

Aug 20 2020

機能コンポーネントを使用していて、Flatlistを使用してデータのリストをレンダリングしていますが、正常に機能していますが、状態が追加のデータを取得するたびに、常に既存のデータが再レンダリングされ、パフォーマンスの問題が発生します。SOからこれらの記事を読みましたが、まだ手がかりなし

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

これがメインフラットリストを使用する私のコードです

<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オブジェクト内の複雑なオブジェクトのみを浅く比較します。比較を制御したい場合は、2番目の引数としてカスタム比較関数を提供することもできます

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

:取得している小道具の数と固有のものがわからない。基本的に、最後のものがこれと等しいことを比較する必要があります。そうすれば、reactはコンポーネントを再レンダリングしません。