我正在为我的应用程序使用带有react和typescript的redux。我正在使用我的应用程序的不同位置使用的许多项目。我的州看起来像这样:
{
items: {42: {}, 53: {}, ... }, //A large dictionary of items
itemPage1: {
itemsId: [ 42, 34, 4 ],
...
},
itemPage2: { ...
},
...
}
用户可以修改items
调度某些操作的某些属性。当发生这种情况时,我需要重绘每个页面中已修改的组件。问题是我的物品很大,我不能在每次小修改时重新绘制所有物品。我想知道这种方法是否有效:
<ItemPage1>
,它连接到商店以获取存储在itemPage1
下的树中的所有状态,例如商品列表ID:itemsId
。<ItemPage1>
内,我遍历itemsId
属性以生成多个FilterItem
组件:itemsId.map( itemId => return <FilterItem id=itemId>);
最后,使用Item
连接每个ownProps
以获取状态的正确部分:
const mapStateToItemProps = (state, ownProps) => {
return {
item: state.items[ownProps.id],
}
}
const mapDispatchToItemProps = (dispatch, ownProps) => {
return null;
}
const FilterItem = connect(
mapStateToItemProps,
mapDispatchToItemProps
)(Item)
如果我更新了id 42的项目,你能否确认或反驳,那么只有这个项目会被重新渲染?
答案 0 :(得分:10)
在渲染大型列表时,您需要考虑以下几点:
基本上,当用户编辑一行时,您要避免的是对列表(或页面)的完全重新呈现。这可以完全按照您的方式实现,即:通过仅将需要呈现的项目的ID传递给列表容器,并使用connect
将这些ID映射到ownProps
每个组件。如果您有转储<Item/>
组件,则您的<ItemPage/>
组件将创建已连接的connect(<Item/>)
组件。
如果您在console.log('item rendered')
组件类中放置<Item/>
,您会注意到只有一个电话。
但是(并且它很大但是),使用react-redux
时不明显的是依赖于ownProps
的所有连接组件将<如果状态的任何部分发生变化,则强烈>始终重新呈现。在您的情况下,即使<Item/>
组件不会重新渲染,它们的包装组件connect(Item)
也会!如果您有几十个项目,如果需要快速调度操作(例如输入输入时),可能会遇到一些延迟。怎么避免呢?使用工厂函数将ownProps
用作初始道具:
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)
我建议你看看this other answer。
您可能也对这些出色的幻灯片感兴趣:Big List High Performance React & Redux
最后,您应该明确地查看react-virtualized来执行列表的虚拟化(即,仅显示用户可以实际看到的项目)。
答案 1 :(得分:0)
好的,我发现了这个讨论:https://github.com/reactjs/redux/issues/1303
在底部清楚地说明了(来自多个主角):
[...] react-redux会解决这个问题。它允许您指定您关注的状态的特定部分,并在相关部分未更改时小心不用更新React组件。
[...]只是想完全理解这里发生了什么,所以如果Redux商店得到更新但是一个特定的组件状态没有改变,Redux将不会触发forceUpdate( )该组件的方法? [...]
React-Redux的connect()函数生成的包装器组件会进行多项检查,以尽量减少实际组件重新呈现的次数。这包括shouldComponentUpdate的默认实现,并对进入组件的props执行浅等式检查(包括从mapStateToProps返回的内容)。所以是的,作为一般规则,连接组件只会在从状态中提取的值发生变化时重新呈现。
所以我相信我的实现很好,它不会重新渲染所有项目,因为只有一个项目会看到它的属性被修改。