Add shallowCompare module and use it in PureRenderMixin + tests

This commit is contained in:
cpojer
2015-03-09 18:49:37 -07:00
parent 62ee384d7b
commit a1631bea71
4 changed files with 176 additions and 3 deletions
@@ -11,7 +11,7 @@
'use strict';
var shallowEqual = require('shallowEqual');
var shallowCompare = require('shallowCompare');
/**
* If your React component's render function is "pure", e.g. it will render the
@@ -39,8 +39,7 @@ var shallowEqual = require('shallowEqual');
*/
var ReactComponentWithPureRenderMixin = {
shouldComponentUpdate: function(nextProps, nextState) {
return !shallowEqual(this.props, nextProps) ||
!shallowEqual(this.state, nextState);
return shallowCompare(this, nextProps, nextState);
}
};
@@ -0,0 +1,145 @@
/**
* Copyright 2015, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @emails react-core
*/
'use strict';
var React;
var ReactComponentWithPureRenderMixin;
var ReactTestUtils;
describe('ReactComponentWithPureRenderMixin', function() {
beforeEach(function() {
React = require('React');
ReactComponentWithPureRenderMixin =
require('ReactComponentWithPureRenderMixin');
ReactTestUtils = require("../../ReactTestUtils");
});
it('provides a default shouldComponentUpdate implementation', function() {
var renderCalls = 0;
class PlasticWrap extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
color: 'green'
};
}
render() {
return (
<Apple
color={this.state.color}
ref="apple"
/>
);
}
}
var Apple = React.createClass({
mixins: [ReactComponentWithPureRenderMixin],
getInitialState: function() {
return {
cut: false,
slices: 1,
}
},
cut: function() {
this.setState({
cut: true,
slices: 10,
});
},
eatSlice: function() {
this.setState({
slices: this.state.slices - 1,
});
},
render: function() {
renderCalls++;
return <div />;
}
});
var instance = ReactTestUtils.renderIntoDocument(<PlasticWrap />);
expect(renderCalls).toBe(1);
// Do not re-render based on props
instance.setState({color: 'green'});
expect(renderCalls).toBe(1);
// Re-render based on props
instance.setState({color: 'red'});
expect(renderCalls).toBe(2);
// Re-render base on state
instance.refs.apple.cut();
expect(renderCalls).toBe(3);
// No re-render based on state
instance.refs.apple.cut();
expect(renderCalls).toBe(3);
// Re-render based on state again
instance.refs.apple.eatSlice();
expect(renderCalls).toBe(4);
});
it('does not do a deep comparison', function() {
function getInitialState() {
return {
foo: [1, 2, 3],
bar: {a: 4, b: 5, c: 6},
};
}
var renderCalls = 0;
var initialSettings = getInitialState();
var Component = React.createClass({
mixins: [ReactComponentWithPureRenderMixin],
getInitialState: function() {
return initialSettings;
},
render: function() {
renderCalls++;
return <div />;
}
});
var instance = ReactTestUtils.renderIntoDocument(<Component />);
expect(renderCalls).toBe(1);
// Do not re-render if state is equal
var settings = {
foo: initialSettings.foo,
bar: initialSettings.bar,
};
instance.setState(settings);
expect(renderCalls).toBe(1);
// Re-render because one field changed
initialSettings.foo = [1, 2, 3];
instance.setState(initialSettings);
expect(renderCalls).toBe(2);
// Re-render because the object changed
instance.setState(getInitialState());
expect(renderCalls).toBe(3);
});
});
+27
View File
@@ -0,0 +1,27 @@
/**
* Copyright 2013-2015, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule shallowCompare
*/
'use strict';
var shallowEqual = require('shallowEqual');
/**
* Does a shallow comparison for props and state.
* See ReactComponentWithPureRenderMixin
*/
function shallowCompare(instance, nextProps, nextState) {
return (
!shallowEqual(instance.props, nextProps) ||
!shallowEqual(instance.state, nextState)
);
}
module.exports = shallowCompare;
+2
View File
@@ -29,6 +29,7 @@ var ReactUpdates = require('ReactUpdates');
var cx = require('cx');
var cloneWithProps = require('cloneWithProps');
var shallowCompare = require('shallowCompare');
var update = require('update');
React.addons = {
@@ -41,6 +42,7 @@ React.addons = {
classSet: cx,
cloneWithProps: cloneWithProps,
createFragment: ReactFragment.create,
shallowCompare: shallowCompare,
update: update
};