Skip to content

Instantly share code, notes, and snippets.

@rosskevin
Created September 12, 2016 17:26
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rosskevin/af84b4e81fe64f3dfc1d1127563dee0b to your computer and use it in GitHub Desktop.
Save rosskevin/af84b4e81fe64f3dfc1d1127563dee0b to your computer and use it in GitHub Desktop.
React Performance/shouldComponentUpdate visibility helper
// @flow
import reShallowEqual from 'recompose/shallowEqual'
import Logger from './Logger'
class Performance {
static shouldComponentUpdate (component, nextProps, nextState, nextContext, dig = false) {
if (!__DEV__) {
return (
!reShallowEqual(this.props, nextProps) || !reShallowEqual(this.state, nextState) || !reShallowEqual(this.context, nextContext)
)
}
else {
const dirty = []
const propsDiff = !shallowEqual(dirty, dig, 'props', component.props, nextProps)
const stateDiff = !shallowEqual(dirty, dig, 'state', component.state, nextState)
const contextDiff = !shallowEqual(dirty, dig, 'context', component.context, nextContext)
const result = propsDiff || stateDiff || contextDiff
if (result) {
this._log(component, `is dirty: ${dirty.join(', ')}`)
}
return result
}
}
// private
static _log (component, ...args) {
log.debug(`[${Logger.objectName(component)}] ${args.join(' ')}`)
}
}
/*
---------------------------------------------------------------------------------------
Below is a copy of shallowEqual, instrumented to aid in finding differences more easily
*/
/* eslint-disable no-self-compare */
const hasOwnProperty = Object.prototype.hasOwnProperty
/**
* inlined Object.is polyfill to avoid requiring consumers ship their own
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
*/
function is (x: mixed, y: mixed): boolean {
// SameValue algorithm
if (x === y) { // Steps 1-5, 7-10
// Steps 6.b-6.e: +0 != -0
return x !== 0 || 1 / (x: $FlowIssue) === 1 / (y: $FlowIssue)
} else {
// Step 6.a: NaN == NaN
return x !== x && y !== y
}
}
/**
* Performs equality by iterating through keys on an object and returning false
* when any key has values which are not strictly equal between the arguments.
* Returns true when the values of all keys are strictly equal.
*/
function shallowEqual (dirty: Array<string>, dig: boolean, name: string, objA: mixed, objB: mixed): boolean {
// always return the result from the known-good recompose library.
const result = reShallowEqual(objA, objB)
if (!dig || result) {
if (!result) {
dirty.push(name)
}
return result
}
// dig below here
let msg = ''
if (!result) {
msg += name
}
if (is(objA, objB)) {
msg += ' (is diff)'
dirty.push(msg)
return result
}
if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) {
msg += ' (null diff)'
dirty.push(msg)
return result
}
const keysA = Object.keys(objA)
const keysB = Object.keys(objB)
if (keysA.length !== keysB.length) {
msg += ' (key length diff)'
dirty.push(msg)
return result
}
// Test for A's keys different from B.
const diffKeys = []
for (let i = 0; i < keysA.length; i++) {
const aKey = keysA[ i ]
if (!hasOwnProperty.call(objB, aKey) || !is(objA[ aKey ], objB[ aKey ])) {
diffKeys.push(aKey)
}
}
msg += ` ([${diffKeys.join(', ')}] keys are diff)`
dirty.push(msg)
return result
}
const log = new Logger(Performance) // eslint-disable-line
export default Performance
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment