Revert "Don't mutate passed-in props"
This reverts https://github.com/facebook/react/pull/576 This approach mutates the default props for the instance on each update, which causes incorrect behavior. discussed with @balpert. can look into cloning but this unbreaks.
Paul Shen committed
Dec 5, 2013 at 16:50 UTC
12e765dd27ed484e462723419ec269e404349ea6
2 files changed
+10
-38
src/core/ReactCompositeComponent.js
+10
-18
@@ -676,7 +676,7 @@ var ReactCompositeComponentMixin = {
676
this._compositeLifeCycleState = CompositeLifeCycle.MOUNTING;
677
678
this._defaultProps = this.getDefaultProps ? this.getDefaultProps() : null;
679
- this.props = this._processProps(this.props);
679
+ this._processProps(this.props);
680
681
if (this.__reactAutoBindMap) {
682
this._bindAutoBindMethods();
@@ -844,31 +844,22 @@ var ReactCompositeComponentMixin = {
844
845
/**
846
* Processes props by setting default values for unspecified props and
847
- * asserting that the props are valid. Does not mutate its argument; returns
848
- * a new props object with defaults merged in.
847
+ * asserting that the props are valid.
848
*
850
- * @param {object} newProps
851
- * @return {object}
849
+ * @param {object} props
850
* @private
851
*/
854
- _processProps: function(newProps) {
855
- var props = this._defaultProps;
856
- if (props) {
857
- // To avoid mutating the props that are passed into the constructor, we
858
- // copy onto the object returned by getDefaultProps instead.
859
- for (var propName in newProps) {
860
- if (typeof newProps[propName] !== 'undefined') {
861
- props[propName] = newProps[propName];
862
- }
852
+ _processProps: function(props) {
853
+ var defaultProps = this._defaultProps;
854
+ for (var propName in defaultProps) {
855
+ if (typeof props[propName] === 'undefined') {
856
+ props[propName] = defaultProps[propName];
857
}
864
- } else {
865
- props = newProps;
858
}
859
var propTypes = this.constructor.propTypes;
860
if (propTypes) {
861
this._checkPropTypes(propTypes, props, ReactPropTypeLocations.prop);
862
}
871
- return props;
863
},
864
865
/**
@@ -920,7 +911,8 @@ var ReactCompositeComponentMixin = {
911
912
var nextProps = this.props;
913
if (this._pendingProps != null) {
923
- nextProps = this._processProps(this._pendingProps);
914
+ nextProps = this._pendingProps;
915
+ this._processProps(nextProps);
916
this._pendingProps = null;
917
918
this._compositeLifeCycleState = CompositeLifeCycle.RECEIVING_PROPS;
src/core/__tests__/ReactCompositeComponent-test.js
-20
@@ -213,26 +213,6 @@ describe('ReactCompositeComponent', function() {
213
reactComponentExpect(instance3).scalarPropsEqual({key: null});
214
});
215
216
- it('should not mutate passed-in props object', function() {
217
- var Component = React.createClass({
218
- getDefaultProps: function() {
219
- return {key: 'testKey'};
220
- },
221
- render: function() {
222
- return <span />;
223
- }
224
- });
225
-
226
- var inputProps = {};
227
- var instance1 = Component(inputProps);
228
- ReactTestUtils.renderIntoDocument(instance1);
229
- expect(instance1.props.key).toBe('testKey');
230
-
231
- // We don't mutate the input, just in case the caller wants to do something
232
- // with it after using it to instantiate a component
233
- expect(inputProps.key).not.toBeDefined();
234
- });
235
-
216
it('should normalize props with default values', function() {
217
var Component = React.createClass({
218
propTypes: {key: ReactPropTypes.string.isRequired},