【发布时间】:2017-08-01 09:14:23
【问题描述】:
我有分层的、递归的数据结构。这是一个命名项目的列表,每个项目都可以有自己的项目子列表。它看起来像这样:
const items = [
{
name: 'item1',
items: [
{name: 'item2'},
{name: 'item3'},
{name: 'item4', items: [
{
name: 'item5'
}
]},
]
},
{
name: 'item6'
}
]
我想将它显示在带有嵌套子列表的无序列表中。此外,我需要能够将某些项目标记为突出显示并取消突出显示所有项目。由于第二个要求,有关突出显示的项目的信息必须存在于顶级组件中。
我的幼稚实现如下所示:
class App extends Component {
constructor() {
super(...arguments)
this.state = {
items: items,
highlightedItemsNames: {},
}
this.handleHighligtItem = (item) => {
this.setState({highlightedItemsNames: {
...this.state.highlightedItemsNames, [item.name]: true
}})
}
this.handleDehighlightAllItems = () => {
this.setState({highlightedItemsNames: {}})
}
}
render() {
return <div>
<button onClick={this.handleDehighlightAllItems}>dehighlight</button>
<List
items={this.state.items}
highlightedItemsNames={this.state.highlightedItemsNames}
onHighlight={this.handleHighligtItem}
/>
</div>
}
}
function List(props) {
return <ul>
{props.items.map(item => <li key={item.name}>
<Item
item={item}
highlighted={props.highlightedItemsNames[item.name]}
highlightedItemsNames={props.highlightedItemsNames}
onHighlight={props.onHighlight}
/>
</li>)}
</ul>
}
function Item(props) {
let className = "item"
if (props.highlighted) {
className += '-highlighted'
}
console.log('renders item', props.item.name)
return <div>
<span className={className}>{props.item.name}</span>
<button onClick={() => props.onHighlight(props.item)}>highlight</button>
{props.item.items ? <List
items={props.item.items}
highlightedItemsNames={props.highlightedItemsNames}
onHighlight={props.onHighlight}
/> : null}
</div>
}
但是现在,当我突出显示一个项目时,highlightedItemsNames 会发生变化,并且每个 Item 都会重新渲染。要正确显示数据,只有突出显示的项目及其父项需要重新渲染。那么如何避免所有这些不必要的重新渲染呢?
在我的应用程序中,项目列表可能有点大,重新渲染所有项目会导致应用程序在点击时明显冻结。
我可以在Item 中实现shouldComponentUpdate 来检查是否应该重新渲染任何子项,但这是否真的有机会提高virtual-dom 的性能?
我没有使用 Redux 或任何其他状态管理库,我现在不想这样做。
【问题讨论】:
-
您需要为元素设置唯一键。否则它总是会重新渲染。
-
@MuratK。项目名称是唯一的 - 所以我在 上有唯一的道具
-
@FabioAntunes 我没有使用 Redux
标签: javascript reactjs