Skip to content
This repository has been archived by the owner on Feb 16, 2021. It is now read-only.

Commit

Permalink
Respect path changes in Component shouldComponentUpdate (#388) (#389)
Browse files Browse the repository at this point in the history
* add update on path change test

* respect path changes in Component `shouldComponentUpdate` method (#388)

* add `isArraysDiffers` util

* compare path array by value instead of reference

* rename `isArraysDiffers` -> `isArraysShallowDiffers`
  • Loading branch information
gbiryukov authored and gcanti committed Jun 16, 2017
1 parent 988fd5a commit eb1c6cf
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 11 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
"karma-webpack": "1.7.0",
"react": "^15.0.0",
"react-dom": "^15.0.0",
"react-test-renderer": "^15.5.4",
"tape": "4.0.0",
"webpack": "1.12.8"
},
Expand Down
22 changes: 12 additions & 10 deletions src/components.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import {
move,
UIDGenerator,
getTypeFromUnion,
getComponentOptions
getComponentOptions,
isArraysShallowDiffers
} from './util'

const Nil = t.Nil
Expand Down Expand Up @@ -116,17 +117,18 @@ export class Component extends React.Component {
}

shouldComponentUpdate(nextProps, nextState) {
const { props, state } = this
const nextPath = Boolean(nextProps.ctx) && nextProps.ctx.path
const curPath = Boolean(props.ctx) && props.ctx.path

const should = (
nextState.value !== this.state.value ||
nextState.hasError !== this.state.hasError ||
nextProps.options !== this.props.options ||
nextProps.type !== this.props.type
nextState.value !== state.value ||
nextState.hasError !== state.hasError ||
nextProps.options !== props.options ||
nextProps.type !== props.type ||
isArraysShallowDiffers(nextPath, curPath)
)
// console.log(nextState.value !== this.state.value,
// nextState.hasError !== this.state.hasError,
// nextProps.options !== this.props.options,
// nextProps.type !== this.props.type,
// should)

return should
}

Expand Down
20 changes: 20 additions & 0 deletions src/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -173,3 +173,23 @@ export function getComponentOptions(options, defaultOptions, value, type) {
}
return opts
}

export function isArraysShallowDiffers(array, other) {
if (array === other) {
return false
}

const { length } = array
if (length !== other.length) {
return true
}

let index = -1
while (++index < length) {
if (array[index] !== other[index]) {
return true
}
}

return false
}
41 changes: 41 additions & 0 deletions test/components/Component.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import tape from 'tape'
import React from 'react'
import t from 'tcomb-validation'
import ShallowRenderer from 'react-test-renderer/shallow'
import { Component, getComponent } from '../../src/components'
import { ctx } from './util'

Expand Down Expand Up @@ -222,4 +224,43 @@ tape('Component', ({ test }) => {
'myid',
'should return the provided id')
})

test('re-render on path change', (assert) => {
assert.plan(2)

let renderCallsNum = 0

class TestComponent extends Component {
render() {
renderCallsNum++
return null
}
}

const renderer = new ShallowRenderer()

const baseProps = {
options: {},
}
const elementA = React.createElement(TestComponent, {
...baseProps,
ctx: {
...ctx,
path: ['foo']
}
})
const elementB = React.createElement(TestComponent, {
...baseProps,
ctx: {
...ctx,
path: ['bar']
}
})

renderer.render(elementA)
assert.strictEqual(renderCallsNum, 1, '#1.1')

renderer.render(elementB)
assert.strictEqual(renderCallsNum, 2, '#1.2')
})
})
19 changes: 18 additions & 1 deletion test/util.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import tape from 'tape'
import { humanize, move } from '../src/util'
import { humanize, move, isArraysShallowDiffers } from '../src/util'

tape('util', ({ test }) => {
test('humanize', (assert) => {
Expand All @@ -15,4 +15,21 @@ tape('util', ({ test }) => {
assert.strictEqual(initial, actual)
assert.deepEqual(actual, expected)
})

test('isArraysShallowDiffers', (assert) => {
assert.plan(4)

const array = ['foo', 1]
let other = ['bar', 1]
assert.equal(isArraysShallowDiffers(array, other), true)

other[0] = 'foo'
assert.equal(isArraysShallowDiffers(array, other), false)

other.push('baz')
assert.equal(isArraysShallowDiffers(array, other), true)

other = array
assert.equal(isArraysShallowDiffers(array, other), false)
})
})

0 comments on commit eb1c6cf

Please sign in to comment.