consistent owner for stateless component (#6534)
yiminghe committed
Apr 18, 2016 at 16:08 UTC
b11540ccb2321aeb7259fcf0b3a38aeeea35231d
3 files changed
+47
-6
src/renderers/shared/stack/reconciler/ReactCompositeComponent.js
+9
-4
@@ -1117,12 +1117,17 @@ var ReactCompositeComponentMixin = {
1117
*/
1118
_renderValidatedComponent: function() {
1119
var renderedComponent;
1120
- ReactCurrentOwner.current = this;
1121
- try {
1120
+ if (__DEV__ || !(this._instance instanceof StatelessComponent)) {
1121
+ ReactCurrentOwner.current = this;
1122
+ try {
1123
+ renderedComponent =
1124
+ this._renderValidatedComponentWithoutOwnerOrContext();
1125
+ } finally {
1126
+ ReactCurrentOwner.current = null;
1127
+ }
1128
+ } else {
1129
renderedComponent =
1130
this._renderValidatedComponentWithoutOwnerOrContext();
1124
- } finally {
1125
- ReactCurrentOwner.current = null;
1131
}
1132
invariant(
1133
// TODO: An `isValidNode` function would probably be more appropriate
src/renderers/shared/stack/reconciler/ReactRef.js
+4
-2
@@ -62,8 +62,10 @@ ReactRef.shouldUpdateRefs = function(prevElement, nextElement) {
62
return (
63
// This has a few false positives w/r/t empty components.
64
prevEmpty || nextEmpty ||
65
- nextElement._owner !== prevElement._owner ||
66
- nextElement.ref !== prevElement.ref
65
+ nextElement.ref !== prevElement.ref ||
66
+ // If owner changes but we have an unchanged function ref, don't update refs
67
+ (typeof nextElement.ref === 'string' &&
68
+ nextElement._owner !== prevElement._owner)
69
);
70
};
71
src/renderers/shared/stack/reconciler/__tests__/refs-test.js
+34
@@ -240,5 +240,39 @@ describe('ref swapping', function() {
240
var instance = ReactTestUtils.renderIntoDocument(<Component />);
241
expect(!!instance.refs).toBe(true);
242
});
243
+
244
+ function testRefCall() {
245
+ var refCalled = 0;
246
+ function Inner(props) {
247
+ return <a ref={props.saveA} />;
248
+ }
249
+ var Outer = React.createClass({
250
+ saveA() {
251
+ refCalled++;
252
+ },
253
+ componentDidMount() {
254
+ this.setState({});
255
+ },
256
+ render() {
257
+ return <Inner saveA={this.saveA} />;
258
+ },
259
+ });
260
+ ReactTestUtils.renderIntoDocument(<Outer />);
261
+ expect(refCalled).toBe(1);
262
+ }
263
+
264
+ it('ref called correctly for stateless component when __DEV__ = false', function() {
265
+ var originalDev = __DEV__;
266
+ __DEV__ = false;
267
+ testRefCall();
268
+ __DEV__ = originalDev;
269
+ });
270
+
271
+ it('ref called correctly for stateless component when __DEV__ = true', function() {
272
+ var originalDev = __DEV__;
273
+ __DEV__ = true;
274
+ testRefCall();
275
+ __DEV__ = originalDev;
276
+ });
277
});
278