【问题标题】:React native VirtualizedList Re-render while scroll the list滚动列表时反应本机 VirtualizedList 重新渲染
【发布时间】:2022-01-13 08:57:05
【问题描述】:

我的虚拟化列表初始渲染记录最多 30 条,同时渲染数据列表自动重新渲染 2 到 4 次,并且新数据添加到列表中

在多次渲染时,我们无法执行任何操作,例如触摸或导航到另一个屏幕

我的代码

class HomeDetails extends PureComponent {
  constructor(props) {
    super(props);
    this.cellRefs = {};
    this.flatListRef = React.createRef();
  }
getItem = (data, index) => {
    if (index in data) {
      return {
        key: `${data[index].id} - ${index}`,
        id: data[index].id,
        accountId: data[index].accountId,
        displayName: data[index].displayName,
        fullName: data[index].fullName,
  
      };
    }
  };

  keyExtractor(item, index) {
    return `${item.id} - ${index}`;
  }

  getItemCount = data => {
    return data.length;
  };

  _renderItem =({item,index}) => {
    console.log(
      'Rerendring',
      item.accountId,
      moment().format('MM/DD/YY hh:mm:ss a'),
    );
    return (
     
        <View key={index} style={{height: 50,  flexDirection: 'row'}}>
          <Text>{`${item.accountId}   ${moment().format(
            'MM/DD/YY hh:mm:ss a',
          )}`}</Text>
        </View>
   
    );

}

render(){
return (
<VirtualizedList
              onScroll={this.onScrollHandler}
              onViewableItemsChanged={this._onViewableItemsChanged}
              viewabilityConfig={viewabilityConfig}
              scrollEventThrottle={16}
              ref={this.flatListRef}
              horizontal={false}
              decelerationRate="normal"
              showsHorizontalScrollIndicator={false}
              showsVerticalScrollIndicator={false}
              data={this.props.responseRecord}
              pagingEnabled={true}
              scrollToOverflowEnabled={false}
              renderItem={this._renderItem}
              keyExtractor={this.keyExtractor}
              getItemCount={this.getItemCount}
              getItem={this.getItem}
              windowSize={21}
              progressViewOffset={20}
              initialNumToRender={15}
              maxToRenderPerBatch={15}
              updateCellsBatchingPeriod={100}
              onEndReached={val => {
                return this.props.getExtraData(2, 1);
              }}
              onEndReachedThreshold={0.1}
              refreshing={this.props.postLoading}
              extraData={this.props.refreshData}
              disableIntervalMomentum={false}
              removeClippedSubviews={true}
              onRefresh={() => {
                return this.props.getExtraData(1, 1);
              }} 
              ItemSeparator={this.ItemSeparator}
              ListFooterComponent={this.renderFooter}
             
            />
)
}
}

const mapStateToProps = ({post, auth, common}) => {
  const {
    responseRecord,
    postLoading,
    refreshData,

  } = post;

  return {
     responseRecord,
    postLoading,
    refreshData,
  };
};

const mapDispatchToProps = {

  getExtraData,

};

export default connect(mapStateToProps, mapDispatchToProps)(HomeDetails);

.................................................. ....................

1.对于最初的 30 条记录,其重新渲染超过 2 次 2.当添加更多记录时,其重新渲染超过 4 到 6 次 3.用purecomponent试过,但没有运气

在小吃中部署的代码 https://snack.expo.dev/@pandianvpsm/cd5737

【问题讨论】:

    标签: reactjs react-native react-native-flatlist rerender


    【解决方案1】:

    在内部,React 的 PureComponent 实现了 shouldComponentUpdate 方法,并将之前的 props 值与新的 props 或 state 值进行比较,以避免不必要的重新渲染。

    这适用于 numbersstringsbooleans 等基本类型值。

    对于引用类型值(objectsarrays),这种比较并不总是准确的。这就是你的行为。 this.props.responseRecord 是一个对象数组(引用类型)。

    我们可以通过实现我们自己的componentShouldUpdate 方法来解决这个问题,如下所示:

      /** Trigger component rerender only new elements added */
       shouldComponentUpdate(nextProps, nextState) {
          return this.props.responseRecord.length !== nextProps.responseRecord.length
       
      }
    
    

    完整代码如下

    class HomeDetails extends React.Component {
      constructor(props) {
        super(props);
        this.cellRefs = {};
        this.flatListRef = React.createRef();
      }
    
      /** Trigger component rerender only new elements added */
      shouldComponentUpdate(nextProps, nextState) {
        return this.props.responseRecord.length !== nextProps.responseRecord;
      }
      getItem = (data, index) => {
        if (index in data) {
          return {
            key: `${data[index].id} - ${index}`,
            id: data[index].id,
            accountId: data[index].accountId,
            displayName: data[index].displayName,
            fullName: data[index].fullName,
          };
        }
      };
    
      keyExtractor(item, index) {
        return `${item.id} - ${index}`;
      }
    
      getItemCount = (data) => {
        return data.length;
      };
    
      _renderItem = ({ item, index }) => {
        console.log(
          "Rerendring",
          item.accountId,
          moment().format("MM/DD/YY hh:mm:ss a")
        );
        return (
          <View key={index} style={{ height: 50, flexDirection: "row" }}>
            <Text>{`${item.accountId}   ${moment().format(
              "MM/DD/YY hh:mm:ss a"
            )}`}</Text>
          </View>
        );
      };
    
      render() {
        return (
          <VirtualizedList
            onScroll={this.onScrollHandler}
            onViewableItemsChanged={this._onViewableItemsChanged}
            viewabilityConfig={viewabilityConfig}
            scrollEventThrottle={16}
            ref={this.flatListRef}
            horizontal={false}
            decelerationRate="normal"
            showsHorizontalScrollIndicator={false}
            showsVerticalScrollIndicator={false}
            data={this.props.responseRecord}
            pagingEnabled={true}
            scrollToOverflowEnabled={false}
            renderItem={this._renderItem}
            keyExtractor={this.keyExtractor}
            getItemCount={this.getItemCount}
            getItem={this.getItem}
            windowSize={21}
            progressViewOffset={20}
            initialNumToRender={15}
            maxToRenderPerBatch={15}
            updateCellsBatchingPeriod={100}
            onEndReached={(val) => {
              return this.props.getExtraData(2, 1);
            }}
            onEndReachedThreshold={0.1}
            refreshing={this.props.postLoading}
            extraData={this.props.refreshData}
            disableIntervalMomentum={false}
            removeClippedSubviews={true}
            onRefresh={() => {
              return this.props.getExtraData(1, 1);
            }}
            ItemSeparator={this.ItemSeparator}
            ListFooterComponent={this.renderFooter}
          />
        );
      }
    }
    
    const mapStateToProps = ({ post, auth, common }) => {
      const { responseRecord, postLoading, refreshData } = post;
    
      return {
        responseRecord,
        postLoading,
        refreshData,
      };
    };
    
    const mapDispatchToProps = {
      getExtraData,
    };
    
    export default connect(mapStateToProps, mapDispatchToProps)(HomeDetails);
    
    
    
    

    【讨论】:

    • 感谢您的回复,但仍然出现连续渲染,我不知道如何解决这个问题,请任何人帮助我
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-27
    • 2022-06-15
    • 1970-01-01
    • 2019-06-05
    • 1970-01-01
    • 2021-03-10
    • 1970-01-01
    相关资源
    最近更新 更多