带有分页结果的 Flatlist 在使用 Redux 附加更多数据时导致重新渲染

Flatlist with Paginated Result Cause Rerender when Appending More Data Using Redux

我正在尝试使用 flatlist 显示来自服务器的信息列表(分页结果)

问题似乎是在加载第二批结果时总是重新呈现整个列表。

平面列表组件

<FlatList
          data={_.size(this.props.search.getIn(['userInfoList','data'])) > 0 ? this.props.search.getIn(['userInfoList', 'data']).toJS() : []}
          renderItem={({item, index}) => this._renderResult(item, index)}
          keyExtractor={(item, index) => index.toString()}
          ListFooterComponent={()=>this._flatlistLoader()}
          ref={(ref) => { this.flatListRef = ref; }}
          ListEmptyComponent={()=>this._emptyList()}
          onEndReachedThreshold={0.5}
          onEndReached={() => this.loadMore()}
          onRefresh={() => this.refreshList()}
          refreshing={this.props.search.userInfoList.isRefreshing}
          initialNumToRender={8}
          maxToRenderPerBatch={5}
        />

shouldComponentUpdate 函数

shouldComponentUpdate(nextProps, nextState){
    return !_.isEqual(nextProps, this.props)
  }

_renderResult(item, index) 函数返回 InfoBox 纯组件

_renderResult(item,index){
    return(
      <InfoBox key={index} item={item}/>
    )
  }

这是我从服务器请求数据后的操作函数的一部分

if(res.status == 200){
                    let newArr = []
                    getState().search.getIn(['userInfoList','data']).map((val) => {
                      newArr.push(val)
                    })
                    res.json.data.data.map((val) => {
                      newArr.push(val)
                    })
                    
                    dispatch(setInfoListResult(newArr))
                  }

那么reducer是这样的

case SET_INFO_LIST_RESULT:
      return state.setIn(['userInfoList', 'data'], fromJS(action.newArr))

我的初始状态 从 'immutable'

导入{记录、列表、地图}
var InitialState = Record({
...
userInfoList: new (Record({
    userid:null,
        total: null,
        lastPage: null,
        data : [],
        perPage : null,
        currentPage : null,
        nextPageUrl: null,
        prevPageUrl:null,
        prevScene:null,
        isFetching:false,
        isRefreshing:false,
        hasError:false,
        hasMoreError:false,
        errorMsg:'',
    }))(),
})

我将 console.log(item.id) 放入 InfoBox (PureComponent) 中,当平面列表开始加载第二页时,它会重新呈现整个列表 2 次并收到警告

VirtualizedList: You have a large list that is slow to update - make sure your renderItem function renders components that follow React performance best practices like PureComponent, shouldComponentUpdate, etc.', { dt: 4913, prevDt: 2441, contentLength: 11064 }

我更新 reducer 列表的方式有问题导致重新渲染?知道如何解决这个问题吗?

.toJS() 将不可变集合转换为 new javascript 对象。因此,每当您的组件运行时 render(),它都会生成一个新对象并触发 FlatList 的渲染。

此外,toJS进行深度转换。您的记录现在再次成为普通可变 javascripts 对象。如果您只需要将集合转换为数组,请使用 toArray

您通常应该避免在任何地方转换集合,这会使 immutablejs 变得无用并且不利于大型数据集的性能。当然,有些组件要求您使用本机数组。您可能希望对这些情况使用某种记忆,例如React.memo, memoize-one, reselect, re-reselect

减少对

的调用量