@samitouri / QOS-React / commits / b11540ccb2

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