-
-
Save nuc/52bfc6e6f42d788d97327aad442bb1da to your computer and use it in GitHub Desktop.
WhyDidYouUpdate Higher Order Component
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* eslint-disable no-console */ | |
import React, { Component } from 'React' | |
import _ from 'lodash' | |
/* | |
* Drop this mixin into a component that wastes | |
* time according to Perf.getWastedTime() to find | |
* out what state/props should be preserved. Once it | |
* says "Update avoidable!" for {state, props}, | |
* you should be able to use shouldComponentUpdate. | |
* | |
* Usage: | |
* | |
* import whyDidYouUpdate from './WhyDidYouUpdate' | |
* | |
* class MyComponent extends Component { | |
* | |
* } | |
* export default whyDidYouUpdate(MyComponent) | |
*/ | |
function isRequiredUpdateObject(o) { | |
return Array.isArray(o) | |
|| (o && o.constructor === Object.prototype.constructor) | |
} | |
function deepDiff(o1, o2, p) { | |
const notify = status => { | |
console.warn('Update %s', status) | |
console.log('%cbefore', 'font-weight: bold', o1) | |
console.log('%cafter ', 'font-weight: bold', o2) | |
} | |
if (!_.isEqual(o1, o2)) { | |
console.group(p) | |
if ([o1, o2].every(_.isFunction)) { | |
notify('avoidable?') | |
} else if (![o1, o2].every(isRequiredUpdateObject)) { | |
notify('required.') | |
} else { | |
const keys = _.union(_.keys(o1), _.keys(o2)) | |
for (const key of keys) { | |
deepDiff(o1[key], o2[key], key) | |
} | |
} | |
console.groupEnd() | |
} else if (o1 !== o2) { | |
console.group(p) | |
notify('avoidable!') | |
if (_.isObject(o1) && _.isObject(o2)) { | |
const keys = _.union(_.keys(o1), _.keys(o2)) | |
for (const key of keys) { | |
deepDiff(o1[key], o2[key], key) | |
} | |
} | |
console.groupEnd() | |
} | |
} | |
const WhyDidYouUpdate = ComposedComponent => class Enhance extends Component { | |
componentDidUpdate(prevProps, prevState) { | |
deepDiff({ props: prevProps, state: prevState }, | |
{ props: this.props, state: this.state }, | |
this.constructor.name) | |
} | |
render() { | |
return <ComposedComponent {...this.props} /> | |
} | |
} | |
export default WhyDidYouUpdate |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment