Remove transferPropsTo
I'd like to outlaw prop mutation altogether, and now seems like a fine time to remove transferPropsTo. Test Plan: jest
Ben Alpert committed
Nov 15, 2014 at 16:01 UTC
c96ea9abf28d7ffa465feb95c39e3dbb52beb050
7 files changed
+22
-255
examples/jquery-bootstrap/js/app.js
+5
-6
@@ -2,12 +2,11 @@
2
// Bootstrap's classes
3
var BootstrapButton = React.createClass({
4
render: function() {
5
- // transferPropsTo() is smart enough to merge classes provided
6
- // to this component.
7
- return this.transferPropsTo(
8
- <a href="javascript:;" role="button" className="btn">
9
- {this.props.children}
10
- </a>
5
+ return (
6
+ <a {...this.props}
7
+ href="javascript:;"
8
+ role="button"
9
+ className={(this.props.className || '') + ' btn'} />
10
);
11
}
12
});
examples/jquery-mobile/js/app.js
+6
-2
@@ -101,11 +101,15 @@ var JQueryMobilePage = React.createClass({
101
},
102
103
render: function() {
104
- return this.transferPropsTo(React.DOM.div(null,
104
+ var props = {};
105
+ for (var key in this.props) {
106
+ props[key] = this.props[key];
107
+ }
108
+ return React.DOM.div(props,
109
JQueryMobileHeader({title:'Page ' + this.props.id, headerTheme:this.props.headerTheme}),
110
JQueryMobileContent(null, this.props.children),
111
JQueryMobileFooter(null)
108
- ));
112
+ );
113
}
114
});
115
perf/lib/todolist.browser.js
+9
-3
@@ -110,8 +110,14 @@ todolist.NewItemForm = React.createClass({
110
return false;
111
},
112
render: function(){
113
- return this.transferPropsTo(
114
- React.DOM.input({ref:"text", onKeyDown:this.props.onEnter && this._handleNewItemKeyDown})
115
- );
113
+ var props = {};
114
+ for (var key in this.props) {
115
+ if (key !== "onEnter") {
116
+ props[key] = this.props[key];
117
+ }
118
+ }
119
+ props.ref = "text";
120
+ props.onKeyDown = this.props.onEnter && this._handleNewItemKeyDown;
121
+ return React.DOM.input(props);
122
}
123
});
src/class/ReactClass.js
-3
@@ -14,7 +14,6 @@
14
var ReactElement = require('ReactElement');
15
var ReactErrorUtils = require('ReactErrorUtils');
16
var ReactInstanceMap = require('ReactInstanceMap');
17
-var ReactPropTransferer = require('ReactPropTransferer');
17
var ReactPropTypeLocations = require('ReactPropTypeLocations');
18
var ReactPropTypeLocationNames = require('ReactPropTypeLocationNames');
19
@@ -826,7 +825,6 @@ var ReactClassMixin = {
825
var ReactClassBase = function() {};
826
assign(
827
ReactClassBase.prototype,
829
- ReactPropTransferer.Mixin,
828
ReactClassMixin
829
);
830
@@ -834,7 +832,6 @@ assign(
832
* Module for creating composite components.
833
*
834
* @class ReactClass
837
- * @extends ReactPropTransferer
835
*/
836
var ReactClass = {
837
src/core/ReactPropTransferer.js
-51
@@ -96,8 +96,6 @@ function transferInto(props, newProps) {
96
*/
97
var ReactPropTransferer = {
98
99
- TransferStrategies: TransferStrategies,
100
-
99
/**
100
* Merge two props objects using TransferStrategies.
101
*
@@ -109,55 +107,6 @@ var ReactPropTransferer = {
107
return transferInto(assign({}, oldProps), newProps);
108
},
109
112
- /**
113
- * @lends {ReactPropTransferer.prototype}
114
- */
115
- Mixin: {
116
-
117
- /**
118
- * Transfer props from this component to a target component.
119
- *
120
- * Props that do not have an explicit transfer strategy will be transferred
121
- * only if the target component does not already have the prop set.
122
- *
123
- * This is usually used to pass down props to a returned root component.
124
- *
125
- * @param {ReactElement} element Component receiving the properties.
126
- * @return {ReactElement} The supplied `component`.
127
- * @final
128
- * @protected
129
- */
130
- transferPropsTo: function(element) {
131
- invariant(
132
- element._owner && element._owner.getPublicInstance() === this,
133
- '%s: You can\'t call transferPropsTo() on a component that you ' +
134
- 'don\'t own, %s. This usually means you are calling ' +
135
- 'transferPropsTo() on a component passed in as props or children.',
136
- this.constructor.displayName,
137
- typeof element.type === 'string' ?
138
- element.type :
139
- element.type.displayName
140
- );
141
-
142
- if (__DEV__) {
143
- if (!didWarn) {
144
- didWarn = true;
145
- warning(
146
- false,
147
- 'transferPropsTo is deprecated. ' +
148
- 'See http://fb.me/react-transferpropsto for more information.'
149
- );
150
- }
151
- }
152
-
153
- // Because elements are immutable we have to merge into the existing
154
- // props object rather than clone it.
155
- transferInto(element.props, this.props);
156
-
157
- return element;
158
- }
159
-
160
- }
110
};
111
112
module.exports = ReactPropTransferer;
src/core/__tests__/ReactPropTransferer-test.js
deleted
-188
@@ -1,188 +0,0 @@
1
-/**
2
- * Copyright 2013-2014, Facebook, Inc.
3
- * All rights reserved.
4
- *
5
- * This source code is licensed under the BSD-style license found in the
6
- * LICENSE file in the root directory of this source tree. An additional grant
7
- * of patent rights can be found in the PATENTS file in the same directory.
8
- *
9
- * @emails react-core
10
- */
11
-
12
-"use strict";
13
-
14
-var React;
15
-var ReactTestUtils;
16
-var reactComponentExpect;
17
-
18
-var TestComponent;
19
-
20
-describe('ReactPropTransferer', function() {
21
-
22
- beforeEach(function() {
23
- require('mock-modules').dumpCache();
24
-
25
- React = require('React');
26
- ReactTestUtils = require('ReactTestUtils');
27
- reactComponentExpect = require('reactComponentExpect');
28
-
29
- // We expect to get a warning from transferPropsTo since it's deprecated
30
- spyOn(console, 'warn');
31
-
32
- TestComponent = React.createClass({
33
- render: function() {
34
- var result = this.transferPropsTo(
35
- <input
36
- className="textinput"
37
- style={{display: 'block', color: 'green'}}
38
- type="text"
39
- value=""
40
- />
41
- );
42
- expect(console.warn).toHaveBeenCalled();
43
- return result;
44
- }
45
- });
46
- });
47
-
48
- it('should leave explicitly specified properties intact', function() {
49
- var instance = <TestComponent type="radio" />;
50
- instance = ReactTestUtils.renderIntoDocument(instance);
51
-
52
- reactComponentExpect(instance)
53
- .expectRenderedChild()
54
- .toBeComponentOfType('input')
55
- .scalarPropsEqual({
56
- className: 'textinput',
57
- style: {display: 'block', color: 'green'},
58
- type: 'text',
59
- value: ''
60
- });
61
- });
62
-
63
- it('should transfer unspecified properties', function() {
64
- var instance = <TestComponent placeholder="Type here..." />;
65
- instance = ReactTestUtils.renderIntoDocument(instance);
66
-
67
- reactComponentExpect(instance)
68
- .expectRenderedChild()
69
- .toBeComponentOfType('input')
70
- .scalarPropsEqual({placeholder: 'Type here...'});
71
- });
72
-
73
- it('should transfer using merge strategies', function() {
74
- var instance =
75
- <TestComponent
76
- className="hidden_elem"
77
- style={{width: '100%', display: 'none'}}
78
- />;
79
- instance = ReactTestUtils.renderIntoDocument(instance);
80
-
81
- reactComponentExpect(instance)
82
- .expectRenderedChild()
83
- .toBeComponentOfType('input')
84
- .scalarPropsEqual({
85
- className: 'textinput hidden_elem',
86
- style: {
87
- color: 'green',
88
- display: 'block',
89
- width: '100%'
90
- }
91
- });
92
- });
93
-
94
- it('should not transfer children', function() {
95
- var ChildrenTestComponent = React.createClass({
96
- render: function() {
97
- return this.transferPropsTo(<div />);
98
- }
99
- });
100
-
101
- var instance =
102
- <ChildrenTestComponent>
103
- <span>Hello!</span>
104
- </ChildrenTestComponent>;
105
-
106
- instance = ReactTestUtils.renderIntoDocument(instance);
107
- reactComponentExpect(instance)
108
- .expectRenderedChild()
109
- .toBeDOMComponentWithTag('div')
110
- .toBeDOMComponentWithNoChildren();
111
- });
112
-
113
- it('should not transfer ref or key', function() {
114
- var TestComponent = React.createClass({
115
- render: function() {
116
- expect(this.props.ref).toBeUndefined();
117
- expect(this.props.key).toBeUndefined();
118
- return <div />;
119
- }
120
- });
121
- var OuterTestComponent = React.createClass({
122
- render: function() {
123
- return this.transferPropsTo(<TestComponent />);
124
- }
125
- });
126
- var OuterOuterTestComponent = React.createClass({
127
- render: function() {
128
- return <OuterTestComponent ref="testref" key="testkey" />;
129
- }
130
- });
131
-
132
- ReactTestUtils.renderIntoDocument(<OuterOuterTestComponent />);
133
- });
134
-
135
- it('should not transferPropsTo() a component you don\'t own', function() {
136
- var Parent = React.createClass({
137
- render: function() {
138
- return <Child><span /></Child>;
139
- }
140
- });
141
-
142
- var Child = React.createClass({
143
- render: function() {
144
- return this.transferPropsTo(this.props.children);
145
- }
146
- });
147
-
148
- expect(function() {
149
- ReactTestUtils.renderIntoDocument(<Parent />);
150
- }).toThrow(
151
- 'Invariant Violation: ' +
152
- 'Child: You can\'t call transferPropsTo() on a component that you ' +
153
- 'don\'t own, span. ' +
154
- 'This usually means you are calling transferPropsTo() on a component ' +
155
- 'passed in as props or children.'
156
- );
157
- });
158
-
159
- it('uses the default instead of the transferred prop (regress)', function() {
160
-
161
- var Child = React.createClass({
162
-
163
- getDefaultProps: function() {
164
- return {
165
- x: 2
166
- };
167
- },
168
-
169
- render: function() {
170
- expect(this.props.x).toBe(2);
171
- return <div />;
172
- }
173
-
174
- });
175
-
176
- var Parent = React.createClass({
177
-
178
- render: function() {
179
- return this.transferPropsTo(<Child />);
180
- }
181
-
182
- });
183
-
184
- ReactTestUtils.renderIntoDocument(<Parent x={5} />);
185
-
186
- });
187
-
188
-});
src/utils/cloneWithProps.js
+2
-2
@@ -25,8 +25,8 @@ var CHILDREN_PROP = keyOf({children: null});
25
* this is to add a CSS class.
26
*
27
* @param {object} child child component you'd like to clone
28
- * @param {object} props props you'd like to modify. They will be merged
29
- * as if you used `transferPropsTo()`.
28
+ * @param {object} props props you'd like to modify. className and style will be
29
+ * merged automatically.
30
* @return {object} a clone of child with props merged in.
31
*/
32
function cloneWithProps(child, props) {