使用 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 添加更多数据时,带有分页结果的平面列表会导致重新渲染的主要内容,如果未能解决你的问题,请参考以下文章