mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Add shallowCompare module and use it in PureRenderMixin + tests
This commit is contained in:
@@ -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);
|
||||
});
|
||||
|
||||
});
|
||||
@@ -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;
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user