Move ref code to ReactCompositeComponent
You can only get a ref to a ReactCompositeComponent, so move the ref code here which gives us more flexibility to put it at the correct time in the lifecycle. There should be no behavior change in this commit. Test Plan: jest
Ben Alpert committed
Jan 22, 2015 at 14:40 UTC
9c3d6b8881dcacdb8a65482bc1da7e96ca7514d6
3 files changed
+67
-55
src/core/ReactComponent.js
-51
@@ -12,27 +12,9 @@
12
'use strict';
13
14
var ReactElementValidator = require('ReactElementValidator');
15
-var ReactOwner = require('ReactOwner');
16
-var ReactRef = require('ReactRef');
15
16
var invariant = require('invariant');
17
20
-function attachRef(ref, component, owner) {
21
- if (ref instanceof ReactRef) {
22
- ReactRef.attachRef(ref, component);
23
- } else {
24
- ReactOwner.addComponentAsRefTo(component, ref, owner);
25
- }
26
-}
27
-
28
-function detachRef(ref, component, owner) {
29
- if (ref instanceof ReactRef) {
30
- ReactRef.detachRef(ref, component);
31
- } else {
32
- ReactOwner.removeComponentAsRefFrom(component, ref, owner);
33
- }
34
-}
35
-
18
/**
19
* Components are the basic units of composition in React.
20
*
@@ -114,12 +96,6 @@ var ReactComponent = {
96
if (__DEV__) {
97
ReactElementValidator.checkAndWarnForMutatedProps(this._currentElement);
98
}
117
-
118
- var ref = this._currentElement.ref;
119
- if (ref != null) {
120
- var owner = this._currentElement._owner;
121
- attachRef(ref, this, owner);
122
- }
99
// Effectively: return '';
100
},
101
@@ -134,10 +110,6 @@ var ReactComponent = {
110
* @internal
111
*/
112
unmountComponent: function() {
137
- var ref = this._currentElement.ref;
138
- if (ref != null) {
139
- detachRef(ref, this, this._currentElement._owner);
140
- }
113
},
114
115
/**
@@ -152,29 +124,6 @@ var ReactComponent = {
124
if (__DEV__) {
125
ReactElementValidator.checkAndWarnForMutatedProps(nextElement);
126
}
155
-
156
- // If either the owner or a `ref` has changed, make sure the newest owner
157
- // has stored a reference to `this`, and the previous owner (if different)
158
- // has forgotten the reference to `this`. We use the element instead
159
- // of the public this.props because the post processing cannot determine
160
- // a ref. The ref conceptually lives on the element.
161
-
162
- // TODO: Should this even be possible? The owner cannot change because
163
- // it's forbidden by shouldUpdateReactComponent. The ref can change
164
- // if you swap the keys of but not the refs. Reconsider where this check
165
- // is made. It probably belongs where the key checking and
166
- // instantiateReactComponent is done.
167
-
168
- if (nextElement._owner !== prevElement._owner ||
169
- nextElement.ref !== prevElement.ref) {
170
- if (prevElement.ref != null) {
171
- detachRef(prevElement.ref, this, prevElement._owner);
172
- }
173
- // Correct, even if the owner is the same, and only the ref has changed.
174
- if (nextElement.ref != null) {
175
- attachRef(nextElement.ref, this, nextElement._owner);
176
- }
177
- }
127
},
128
129
/**
src/core/ReactCompositeComponent.js
+8
-1
@@ -20,6 +20,7 @@ var ReactInstanceMap = require('ReactInstanceMap');
20
var ReactPerf = require('ReactPerf');
21
var ReactPropTypeLocations = require('ReactPropTypeLocations');
22
var ReactPropTypeLocationNames = require('ReactPropTypeLocationNames');
23
+var ReactRef = require('ReactRef');
24
var ReactUpdates = require('ReactUpdates');
25
26
var assign = require('Object.assign');
@@ -173,6 +174,8 @@ var ReactCompositeComponentMixin = assign({},
174
context
175
);
176
177
+ ReactRef.attachRefs(this, this._currentElement);
178
+
179
this._context = context;
180
this._mountOrder = nextMountID++;
181
this._rootNodeID = rootID;
@@ -302,6 +305,8 @@ var ReactCompositeComponentMixin = assign({},
305
this._pendingCallbacks = null;
306
this._pendingElement = null;
307
308
+ ReactRef.detachRefs(this, this._currentElement);
309
+
310
ReactComponent.Mixin.unmountComponent.call(this);
311
312
ReactComponentEnvironment.unmountIDFromEnvironment(this._rootNodeID);
@@ -702,7 +707,6 @@ var ReactCompositeComponentMixin = assign({},
707
prevUnmaskedContext,
708
nextUnmaskedContext
709
) {
705
- // Update refs regardless of what shouldComponentUpdate returns
710
ReactComponent.Mixin.updateComponent.call(
711
this,
712
transaction,
@@ -712,6 +716,9 @@ var ReactCompositeComponentMixin = assign({},
716
nextUnmaskedContext
717
);
718
719
+ // Update refs regardless of what shouldComponentUpdate returns
720
+ ReactRef.updateRefs(this, prevParentElement, nextParentElement);
721
+
722
var inst = this._instance;
723
724
var prevContext = inst.context;
src/core/ReactRef.js
+59
-3
@@ -11,6 +11,7 @@
11
12
'use strict';
13
14
+var ReactOwner = require('ReactOwner');
15
var ReactUpdates = require('ReactUpdates');
16
17
var accumulate = require('accumulate');
@@ -81,16 +82,71 @@ assign(ReactRef.prototype, {
82
}
83
});
84
84
-ReactRef.attachRef = function(ref, value) {
85
+function attachFirstClassRef(ref, value) {
86
ref._value = value.getPublicInstance();
86
-};
87
+}
88
88
-ReactRef.detachRef = function(ref, value) {
89
+function detachFirstClassRef(ref, value) {
90
// Check that `component` is still the current ref because we do not want to
91
// detach the ref if another component stole it.
92
if (ref._value === value) {
93
ref._value = null;
94
}
95
+}
96
+
97
+function attachRef(ref, component, owner) {
98
+ if (ref instanceof ReactRef) {
99
+ attachFirstClassRef(ref, component);
100
+ } else {
101
+ ReactOwner.addComponentAsRefTo(component, ref, owner);
102
+ }
103
+}
104
+
105
+function detachRef(ref, component, owner) {
106
+ if (ref instanceof ReactRef) {
107
+ detachFirstClassRef(ref, component);
108
+ } else {
109
+ ReactOwner.removeComponentAsRefFrom(component, ref, owner);
110
+ }
111
+}
112
+
113
+ReactRef.attachRefs = function(instance, element) {
114
+ var ref = element.ref;
115
+ if (ref != null) {
116
+ attachRef(ref, instance, element._owner);
117
+ }
118
+};
119
+
120
+ReactRef.updateRefs = function(instance, prevElement, nextElement) {
121
+ // If either the owner or a `ref` has changed, make sure the newest owner
122
+ // has stored a reference to `this`, and the previous owner (if different)
123
+ // has forgotten the reference to `this`. We use the element instead
124
+ // of the public this.props because the post processing cannot determine
125
+ // a ref. The ref conceptually lives on the element.
126
+
127
+ // TODO: Should this even be possible? The owner cannot change because
128
+ // it's forbidden by shouldUpdateReactComponent. The ref can change
129
+ // if you swap the keys of but not the refs. Reconsider where this check
130
+ // is made. It probably belongs where the key checking and
131
+ // instantiateReactComponent is done.
132
+
133
+ if (nextElement._owner !== prevElement._owner ||
134
+ nextElement.ref !== prevElement.ref) {
135
+ if (prevElement.ref != null) {
136
+ detachRef(prevElement.ref, instance, prevElement._owner);
137
+ }
138
+ // Correct, even if the owner is the same, and only the ref has changed.
139
+ if (nextElement.ref != null) {
140
+ attachRef(nextElement.ref, instance, nextElement._owner);
141
+ }
142
+ }
143
+};
144
+
145
+ReactRef.detachRefs = function(instance, element) {
146
+ var ref = element.ref;
147
+ if (ref != null) {
148
+ detachRef(ref, instance, element._owner);
149
+ }
150
};
151
152
module.exports = ReactRef;