Remove transferPropsTo

I'd like to outlaw prop mutation altogether, and now seems like a fine time to remove transferPropsTo.

Test Plan: jest
This commit is contained in:
Ben Alpert
2014-11-16 17:41:07 -08:00
parent f391b7b3ca
commit c96ea9abf2
7 changed files with 22 additions and 255 deletions
+5 -6
View File
@@ -2,12 +2,11 @@
// Bootstrap's classes
var BootstrapButton = React.createClass({
render: function() {
// transferPropsTo() is smart enough to merge classes provided
// to this component.
return this.transferPropsTo(
<a href="javascript:;" role="button" className="btn">
{this.props.children}
</a>
return (
<a {...this.props}
href="javascript:;"
role="button"
className={(this.props.className || '') + ' btn'} />
);
}
});
+6 -2
View File
@@ -101,11 +101,15 @@ var JQueryMobilePage = React.createClass({
},
render: function() {
return this.transferPropsTo(React.DOM.div(null,
var props = {};
for (var key in this.props) {
props[key] = this.props[key];
}
return React.DOM.div(props,
JQueryMobileHeader({title:'Page ' + this.props.id, headerTheme:this.props.headerTheme}),
JQueryMobileContent(null, this.props.children),
JQueryMobileFooter(null)
));
);
}
});
+9 -3
View File
@@ -110,8 +110,14 @@ todolist.NewItemForm = React.createClass({
return false;
},
render: function(){
return this.transferPropsTo(
React.DOM.input({ref:"text", onKeyDown:this.props.onEnter && this._handleNewItemKeyDown})
);
var props = {};
for (var key in this.props) {
if (key !== "onEnter") {
props[key] = this.props[key];
}
}
props.ref = "text";
props.onKeyDown = this.props.onEnter && this._handleNewItemKeyDown;
return React.DOM.input(props);
}
});
-3
View File
@@ -14,7 +14,6 @@
var ReactElement = require('ReactElement');
var ReactErrorUtils = require('ReactErrorUtils');
var ReactInstanceMap = require('ReactInstanceMap');
var ReactPropTransferer = require('ReactPropTransferer');
var ReactPropTypeLocations = require('ReactPropTypeLocations');
var ReactPropTypeLocationNames = require('ReactPropTypeLocationNames');
@@ -826,7 +825,6 @@ var ReactClassMixin = {
var ReactClassBase = function() {};
assign(
ReactClassBase.prototype,
ReactPropTransferer.Mixin,
ReactClassMixin
);
@@ -834,7 +832,6 @@ assign(
* Module for creating composite components.
*
* @class ReactClass
* @extends ReactPropTransferer
*/
var ReactClass = {
-51
View File
@@ -96,8 +96,6 @@ function transferInto(props, newProps) {
*/
var ReactPropTransferer = {
TransferStrategies: TransferStrategies,
/**
* Merge two props objects using TransferStrategies.
*
@@ -109,55 +107,6 @@ var ReactPropTransferer = {
return transferInto(assign({}, oldProps), newProps);
},
/**
* @lends {ReactPropTransferer.prototype}
*/
Mixin: {
/**
* Transfer props from this component to a target component.
*
* Props that do not have an explicit transfer strategy will be transferred
* only if the target component does not already have the prop set.
*
* This is usually used to pass down props to a returned root component.
*
* @param {ReactElement} element Component receiving the properties.
* @return {ReactElement} The supplied `component`.
* @final
* @protected
*/
transferPropsTo: function(element) {
invariant(
element._owner && element._owner.getPublicInstance() === this,
'%s: You can\'t call transferPropsTo() on a component that you ' +
'don\'t own, %s. This usually means you are calling ' +
'transferPropsTo() on a component passed in as props or children.',
this.constructor.displayName,
typeof element.type === 'string' ?
element.type :
element.type.displayName
);
if (__DEV__) {
if (!didWarn) {
didWarn = true;
warning(
false,
'transferPropsTo is deprecated. ' +
'See http://fb.me/react-transferpropsto for more information.'
);
}
}
// Because elements are immutable we have to merge into the existing
// props object rather than clone it.
transferInto(element.props, this.props);
return element;
}
}
};
module.exports = ReactPropTransferer;
@@ -1,188 +0,0 @@
/**
* Copyright 2013-2014, 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 ReactTestUtils;
var reactComponentExpect;
var TestComponent;
describe('ReactPropTransferer', function() {
beforeEach(function() {
require('mock-modules').dumpCache();
React = require('React');
ReactTestUtils = require('ReactTestUtils');
reactComponentExpect = require('reactComponentExpect');
// We expect to get a warning from transferPropsTo since it's deprecated
spyOn(console, 'warn');
TestComponent = React.createClass({
render: function() {
var result = this.transferPropsTo(
<input
className="textinput"
style={{display: 'block', color: 'green'}}
type="text"
value=""
/>
);
expect(console.warn).toHaveBeenCalled();
return result;
}
});
});
it('should leave explicitly specified properties intact', function() {
var instance = <TestComponent type="radio" />;
instance = ReactTestUtils.renderIntoDocument(instance);
reactComponentExpect(instance)
.expectRenderedChild()
.toBeComponentOfType('input')
.scalarPropsEqual({
className: 'textinput',
style: {display: 'block', color: 'green'},
type: 'text',
value: ''
});
});
it('should transfer unspecified properties', function() {
var instance = <TestComponent placeholder="Type here..." />;
instance = ReactTestUtils.renderIntoDocument(instance);
reactComponentExpect(instance)
.expectRenderedChild()
.toBeComponentOfType('input')
.scalarPropsEqual({placeholder: 'Type here...'});
});
it('should transfer using merge strategies', function() {
var instance =
<TestComponent
className="hidden_elem"
style={{width: '100%', display: 'none'}}
/>;
instance = ReactTestUtils.renderIntoDocument(instance);
reactComponentExpect(instance)
.expectRenderedChild()
.toBeComponentOfType('input')
.scalarPropsEqual({
className: 'textinput hidden_elem',
style: {
color: 'green',
display: 'block',
width: '100%'
}
});
});
it('should not transfer children', function() {
var ChildrenTestComponent = React.createClass({
render: function() {
return this.transferPropsTo(<div />);
}
});
var instance =
<ChildrenTestComponent>
<span>Hello!</span>
</ChildrenTestComponent>;
instance = ReactTestUtils.renderIntoDocument(instance);
reactComponentExpect(instance)
.expectRenderedChild()
.toBeDOMComponentWithTag('div')
.toBeDOMComponentWithNoChildren();
});
it('should not transfer ref or key', function() {
var TestComponent = React.createClass({
render: function() {
expect(this.props.ref).toBeUndefined();
expect(this.props.key).toBeUndefined();
return <div />;
}
});
var OuterTestComponent = React.createClass({
render: function() {
return this.transferPropsTo(<TestComponent />);
}
});
var OuterOuterTestComponent = React.createClass({
render: function() {
return <OuterTestComponent ref="testref" key="testkey" />;
}
});
ReactTestUtils.renderIntoDocument(<OuterOuterTestComponent />);
});
it('should not transferPropsTo() a component you don\'t own', function() {
var Parent = React.createClass({
render: function() {
return <Child><span /></Child>;
}
});
var Child = React.createClass({
render: function() {
return this.transferPropsTo(this.props.children);
}
});
expect(function() {
ReactTestUtils.renderIntoDocument(<Parent />);
}).toThrow(
'Invariant Violation: ' +
'Child: You can\'t call transferPropsTo() on a component that you ' +
'don\'t own, span. ' +
'This usually means you are calling transferPropsTo() on a component ' +
'passed in as props or children.'
);
});
it('uses the default instead of the transferred prop (regress)', function() {
var Child = React.createClass({
getDefaultProps: function() {
return {
x: 2
};
},
render: function() {
expect(this.props.x).toBe(2);
return <div />;
}
});
var Parent = React.createClass({
render: function() {
return this.transferPropsTo(<Child />);
}
});
ReactTestUtils.renderIntoDocument(<Parent x={5} />);
});
});
+2 -2
View File
@@ -25,8 +25,8 @@ var CHILDREN_PROP = keyOf({children: null});
* this is to add a CSS class.
*
* @param {object} child child component you'd like to clone
* @param {object} props props you'd like to modify. They will be merged
* as if you used `transferPropsTo()`.
* @param {object} props props you'd like to modify. className and style will be
* merged automatically.
* @return {object} a clone of child with props merged in.
*/
function cloneWithProps(child, props) {