使用 Redux 添加更多数据时,带有分页结果的平面列表会导致重新渲染

Posted

技术标签:

【中文标题】使用 Redux 添加更多数据时,带有分页结果的平面列表会导致重新渲染【英文标题】:Flatlist with Paginated Result Cause Rerender when Appending More Data Using Redux 【发布时间】:2021-01-13 13:12:12 【问题描述】:

我正在尝试使用 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))

我的初始状态 从“不可变”导入 Record, List, Map

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:你有一个更新缓慢的大列表 - make 确保您的 renderItem 函数呈现遵循 React 的组件 性能最佳实践,例如 PureComponent、shouldComponentUpdate、 等', dt:4913,prevDt:2441,contentLength:11064

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

【问题讨论】:

【参考方案1】:

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

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

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

减少调用次数

【讨论】:

以上是关于使用 Redux 添加更多数据时,带有分页结果的平面列表会导致重新渲染的主要内容,如果未能解决你的问题,请参考以下文章

滚动到表格底部时如何添加“加载更多”页面

使用带有分页和排序的 ajax 将行动态添加到数据表

如何在 Redux 中构建分页状态 [关闭]

React Redux表单提交未给出正确的结果

如何对搜索结果进行分页?

PFQueryTableViewController 带来重复的结果 - 分页