Javascript 为什么我应该避免在shouldComponentUpdate中使用u.isEqual
这个问题我已经读了很多遍,每次建议的答案都是不要进行深入的比较,因为这样做代价高昂。我已经尝试在我的应用程序中实现这一点,它看起来确实非常快Javascript 为什么我应该避免在shouldComponentUpdate中使用u.isEqual,javascript,html,reactjs,Javascript,Html,Reactjs,这个问题我已经读了很多遍,每次建议的答案都是不要进行深入的比较,因为这样做代价高昂。我已经尝试在我的应用程序中实现这一点,它看起来确实非常快 shouldComponentUpdate = (nextProps, nextState) => { let a = +new Date(); let equalProps = _.isEqual(this.props, nextProps); let equalState = _.isEqual(this.state,
shouldComponentUpdate = (nextProps, nextState) => {
let a = +new Date();
let equalProps = _.isEqual(this.props, nextProps);
let equalState = _.isEqual(this.state, nextState);
let b = +new Date();
console.log("----> deep equality navbar took ", b - a, " result = ", equalProps && equalState);
if (equalProps && equalState) return false;
return true;
};
下面是一个生产的原木样本:
----> deep equality msg list took 0 result = false
----> deep equality msg list took 0 result = false
----> deep equality navbar took 0 result = true
----> deep equality sidebar took 0 result = true
----> deep equality msg list took 1 result = false
基本上,它似乎永远不会超过1毫秒,我正在处理一些6/7级别的嵌套对象。消息列表的呈现时间通常超过70毫秒。。我可以用不到1毫秒的函数调用轻松避免
我错过了一件大事?这似乎是真的。。烤我:这是因为您使用的是小样本数据,所以没有发现任何速度问题,如果有大数据要比较,那么这将是一个大问题,因为组件应该在每次状态更新时运行更新,所以如果lodash.isEqual需要一些时间,它将降低页面渲染速度 您可以在下面看到一个对象比较列表,并找到您项目的最佳对象
fast-deep-equal x 226,960 ops/sec ±1.55% (86 runs sampled)
nano-equal x 218,210 ops/sec ±0.79% (89 runs sampled)
shallow-equal-fuzzy x 206,762 ops/sec ±0.84% (88 runs sampled)
underscore.isEqual x 128,668 ops/sec ±0.75% (91 runs sampled)
lodash.isEqual x 44,895 ops/sec ±0.67% (85 runs sampled)
deep-equal x 51,616 ops/sec ±0.96% (90 runs sampled)
deep-eql x 28,218 ops/sec ±0.42% (85 runs sampled)
assert.deepStrictEqual x 1,777 ops/sec ±1.05% (86 runs sampled)
ramda.equals x 13,466 ops/sec ±0.82% (86 runs sampled)
The fastest is fast-deep-equal
您可以简单地利用日期对象并与之进行比较,让组件知道是否需要重新提交,而不是在状态或属性更改时反复将大型数据集与自身进行比较。例如,如果消息数据发生更改,则可以更新检索到的日期对象;现在,与其进行大数据比较,不如将其与自身进行比较:
class MessageList extends Component {
state = {
retrieved: {},
messages: [],
err: ''
}
fetchMessages = () => {
this.props.fetchMessages()
.then(({data}) => this.setState({ messages: data, retrieved: new Date() }))
.catch(err => this.setState({ err: err.toString() }))
shouldComponentUpdate = (nextProps, nextState) => (
nextState.retrieved > this.state.retrieved || nextState.err !== this.state.err
) // this would compare a retrieved date and/or an err; it will only rerender if either has changed
render = () => ( ... )
}
即使您的应用程序扩展到包含更多数据、更多道具和更多状态,这将在浏览器和不同设备之间保持一致。谢谢您的回答,但我不会使用小样本数据。我正在使用webmail项目中的生产数据。消息列表实际上包含50封完整的电子邮件和许多其他东西…,边栏作为道具接收~1000个文件夹、标签等。。。这些实体中的每一个都是嵌套的,复杂的对象在聚会上有点晚,但这仍然是一个相当小的样本量。我曾经开发过一个react/redux应用程序,它每分钟处理数百万条消息,甚至与某些应用程序的要求不符。@GMchris我对这种情况下的性能很好奇,如果使用isEqual,还可以吗?例如,将以前的状态与当前状态进行比较?@SangĐặ我想说,你需要有点选择性。我使用recompose的shouldUpdate方法制作了这个包装器const propsEqual=props=>shouldUpdatecurr,next=>{if!props返回!\uu.isEqualcurr,next;对于let i=0,prop;i