我开始看到性能问题并尝试对其进行优化。
作为第一步,我正在处理Perf.printWasted()
这就是我试图消除不必要的渲染。
我的一个组件因为两个道具而被重新渲染
new
日期对象。
新创建的[todo]
数组
假设您正在为待办事项创建日历 对于每个日期,我都会传递一个日期,以及当天到期的待办事项列表 我正在做(简化)
之类的事情todoForDay = _.filter(todos, (todo) => {return todo.dueDate == today})
反应的浅层等等不会认为这两种情况是平等的,我该怎么办?
对于#1,我可以考虑将moment(date).format()
作为道具传递,并在每次通过日期时转换回日期对象。
但它会变得非常烦人,因为有太多的子组件需要访问日期。
答案 0 :(得分:1)
您是否尝试过实施shouldComponentUpdate
生命周期方法?您可以检查传入日期prop和todos数组的不等式,如下所示:
class MyComponent extends Component {
shouldComponentUpdate(prevProps) {
const {
date,
todos,
} = this.props;
const {
date: prevDate,
todos: prevTodos,
} = prevProps;
return (
date.getTime() !== prevDate.getTime() ||
!_.isEqual(todos, prevTodos)
);
}
render() {
// render...
}
}
_.isEqual
方法对两个todos
数组进行深度相等比较。如果您想要更具体,还可以使用_.isEqualWith
方法为这些数组定义自己的相等概念。
或者,您可以查看类似于Immutable.js的内容,因为它可以让您进行更轻松的todos !== prevTodos
比较,但这可能对您的需求有些过分(取决于您工作的数据量)用)。
如果您已经做过类似的事情,可能会提供更多代码(您实施的shouldComponentUpdate
方法,以便我们建议其他方法)。
答案 1 :(得分:0)
对于#1,你不需要转换道具。您只需将日期与getTime()
中的shouldComponentUpdate()
进行比较:
shouldComponentUpdate(nextProps) {
return this.props.date.getTime() !== nextProps.date.getTime()
}
对于#2而言,不幸的是它看起来像一个包含对象的数组,我认为在这里做一个深度相等的东西比仅仅渲染更昂贵。
请注意,执行render()
并不意味着DOM会获得更新。如果您正确设置key
,那么它应该足够快。 (如果待办事项可能会更改其顺序,或者新添加的待办事项被添加到顶部,则不要使用索引作为密钥。在这种情况下,真正的唯一密钥更好)
您应该尽量避免不必要的setState
(如果您没有使用状态管理库)。还尝试将组件拆分为小块。而不是每次更新时重新渲染一个巨大的组件,只更新应用程序的最小部分应该更快。
另一种可能性是重建你的国家。但它基于您的要求。如果您不需要每个待办事项的完整日期时间,您可以将您的状态分组为:
todos: {
'2017-04-28': ['Watch movie', 'Jogging'],
'2017-04-29': ['Buy milk']
}
通过这样做,您甚至不需要过滤器。你可以轻松地抓住你想要的日期。
在更复杂的情况下,您需要更多信息,您可以尝试规范化您的州,例如:
{
todos: {
1: { text: 'Watch movie', completed: true, addedTime: 1493476371925 },
2: { text: 'Jogging', completed: true, addedTime: xxxxxxxxxx},
3: { text: 'Buy milk', completed: false, addedTime: xxxxxxxxxx}
},
byDate: {
'2017-04-28': [1, 2],
'2017-04-29': [3]
}
}
现在,如果向todos
添加新的待办事项,则不会影响您引用byDate
的组件,因此您可以确保没有不必要的重新渲染。< / p>
答案 2 :(得分:0)
我正在分享我的解决方案。
对于基于日历的待办事项列表,我希望避免在一个日历日为每个子组件实施shouldComponentUpdate
。
所以我找了一种方法来缓存我为日历创建的日期。 (除非您更改月份,否则您会看到相同的日期范围)。
所以https://github.com/reactjs/reselect非常适合。
我也用重新选择解决了#2。
它记忆(缓存)函数结果直到函数params改变。