避免使用 react-redux 重新渲染大量项目 [英] Avoid re-rendering a big list of items with react-redux

查看:82
本文介绍了避免使用 react-redux 重新渲染大量项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为我的应用程序使用带有 react 和 typescript 的 redux.我正在处理在我的应用程序的不同位置使用的许多项目.我的状态是这样的:

I am using redux with react and typescript for my application. I am working with many items used at different places of my app. My state looks like this:

{
    items: {42: {}, 53: {}, ... }, //A large dictionary of items
    itemPage1: {
        itemsId: [ 42, 34, 4 ],
        ...
    },
    itemPage2: { ... 
    },
    ...
}

用户可以修改items的一些属性来调度一些动作.发生这种情况时,我需要重新绘制每个页面中已修改的组件.问题是我的项目非常大,我无法在每次小的修改时重新绘制所有项目.我想知道这种方法是否有效:

The user can modify some attributes of the items dispatching some actions. When this happen I need to redraw the components that have been modified in each pages. The issue is that my items are quite big and I cant afford to redraw all of them at each small modification. I was wondering is this approach would work:

  • 我有一个第一个组件 ,它连接到商店以获取存储在 itemPage1 下的树中的所有状态,例如项目 ID 列表:itemsId.
  • 中,我循环遍历itemsId 属性以生成多个FilterItem 组件:itemsId.map( itemId=> return );
  • 最后每个 Item 使用 ownProps 连接以获得正确的状态部分:

  • I have a fist component <ItemPage1> which connects to the store to get all of the states stored in the tree under itemPage1 e.g. the list of items id: itemsId.
  • Inside <ItemPage1>, I loop over the itemsId property to generate multiple FilterItem components: itemsId.map( itemId => return <FilterItem id=itemId>);
  • Finally each Item is connected using ownProps to get the correct part of the state:

const mapStateToItemProps = (state, ownProps) => {
    return {
        item: state.items[ownProps.id],
    }
}
const mapDispatchToItemProps = (dispatch, ownProps) => {
    return null;
}
const FilterItem = connect(
    mapStateToItemProps,
    mapDispatchToItemProps
)(Item)

你能否确认或反驳,如果我更新了 id 42 的项目,那么只有这个项目会被重新渲染?

Can you confirm or refute that if I update the item of id 42, then only this item is going to be re-rendered ?

推荐答案

渲染大列表时,您需要考虑以下几点:

When rendering big list you need to take into considerations few things :

  • 减少需要渲染的 DOM 元素总数(通过不渲染在屏幕上实际不可见的项目,也称为虚拟化)
  • 不要重新渲染没有改变的项目

基本上,您要避免的是在用户编辑一行时完全重新呈现您的列表(或您的页面).这可以完全按照您的方式实现,即:通过仅将需要呈现的项目的 id 传递给列表容器,并使用 将这些 id 映射到 connect 每个组件>ownProps.如果你有一个转储 组件,你的 组件将创建连接的 connect() 组件.

Basically, what you want to avoid is a complete re-render of your list (or your page) when the user edits one single row. This can be achieved exactly how you did it, i.e : by passing to the list container only the ids of items that need to be rendered, and to map over these ids to connect each component by using ownProps. If you have a dump <Item/> component, your <ItemPage/> component will create connected connect(<Item/>) component.

这将起作用,如果您在 <Item/> 组件类中放置了 console.log('item render'),您会注意到只有一个电话.

This is going to work, if your put a console.log('item rendered') in your <Item/> component class you will notice that there is only one call.

但是(这是一个很大的但是),使用 react-redux 时不明显的是所有依赖于它们的 ownProps<的连接组件如果状态的任何部分发生变化,/code> 将总是重新渲染.在您的情况下,即使 组件不会重新渲染,它们包装的组件 connect(Item) 也会!如果您有几十个项目,如果需要快速调度操作(例如在输入时输入),您可能会遇到一些延迟.如何避免这种情况?使用工厂函数使用 ownProps 作为初始道具:

BUT (and it's a big but), what is not obvious when working with react-redux is that all connected components that depends on their ownProps will always rerender if any part of the state change. In your case, even if the <Item/> components will not re-render, their wrapped component connect(Item) will ! If you have few dozens of items, you might encounter some latency if actions need to be dispatched quickly (for example when typing in an input). How to avoid that ? Use a factory function to use ownProps as the initial props :

const mapStateToItemProps = (_, initialProps) => (state) => {
    return {
        item: state.items[initialProps.id],  // we're not relying on the second parameters "ownProps" here, so the wrapper component will not rerender
    }
}
const mapDispatchToItemProps = (dispatch, ownProps) => {
    return null;
}
const FilterItem = connect(
    mapStateToItemProps,
    mapDispatchToItemProps
)(Item)

我建议你看看这个其他答案.

您可能还对这些优秀的幻灯片感兴趣:Big List High Performance React &还原

You might also be interested in these excellent slides : Big List High Performance React & Redux

最后,你应该明确地看看 react-virtualized 来执行虚拟化您的列表(即,仅显示用户实际可以看到的项目).

And finally, you should definitively take a look to react-virtualized to perform the virtualization of your list (i.e, displaying only the item that the user can actually see).

这篇关于避免使用 react-redux 重新渲染大量项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆