@samitouri / QOS-React / commits / 9921e57272

Warn when nesting 15 subtree inside 16 (#10434)

Ben Alpert committed Aug 13, 2017 at 16:03 UTC 9921e572722c0fa9d3cda65317f6de60f5d0919f
3 files changed +53 -4
src/renderers/dom/shared/__tests__/renderSubtreeIntoContainer-test.js
+24
@@ -14,6 +14,7 @@
14 var React = require('react');
15 var PropTypes = require('prop-types');
16 var ReactDOM = require('react-dom');
17 +var ReactDOMFeatureFlags = require('ReactDOMFeatureFlags');
18 var ReactTestUtils = require('react-dom/test-utils');
19 var renderSubtreeIntoContainer = require('react-dom')
20 .unstable_renderSubtreeIntoContainer;
@@ -299,4 +300,27 @@ describe('renderSubtreeIntoContainer', () => {
300 ReactDOM.render(<Parent value="foo" />, container);
301 expect(portal2.textContent).toBe('foo');
302 });
303 +
304 + if (ReactDOMFeatureFlags.useFiber) {
305 + it('fails gracefully when mixing React 15 and 16', () => {
306 + class C extends React.Component {
307 + render() {
308 + return <div />;
309 + }
310 + }
311 + const c = ReactDOM.render(<C />, document.createElement('div'));
312 + // React 15 calls this:
313 + // https://github.com/facebook/react/blob/77b71fc3c4/src/renderers/dom/client/ReactMount.js#L478-L479
314 + expect(() => {
315 + c._reactInternalInstance._processChildContext({});
316 + }).toThrow(
317 + '_processChildContext is not available in React 16+. This likely ' +
318 + 'means you have multiple copies of React and are attempting to nest ' +
319 + 'a React 15 tree inside a React 16 tree using ' +
320 + "unstable_renderSubtreeIntoContainer, which isn't supported. Try to " +
321 + 'make sure you have only one copy of React (and ideally, switch to ' +
322 + 'ReactDOM.unstable_createPortal).',
323 + );
324 + });
325 + }
326 });
src/renderers/shared/fiber/ReactFiberClassComponent.js
+25
@@ -40,6 +40,7 @@ var getComponentName = require('getComponentName');
40 var shallowEqual = require('fbjs/lib/shallowEqual');
41 var invariant = require('fbjs/lib/invariant');
42
43 +const fakeInternalInstance = {};
44 const isArray = Array.isArray;
45
46 if (__DEV__) {
@@ -54,6 +55,27 @@ if (__DEV__) {
55 callback,
56 );
57 };
58 +
59 + // This is so gross but it's at least non-critical and can be removed if
60 + // it causes problems. This is meant to give a nicer error message for
61 + // ReactDOM15.unstable_renderSubtreeIntoContainer(reactDOM16Component,
62 + // ...)) which otherwise throws a "_processChildContext is not a function"
63 + // exception.
64 + Object.defineProperty(fakeInternalInstance, '_processChildContext', {
65 + enumerable: false,
66 + value: function() {
67 + invariant(
68 + false,
69 + '_processChildContext is not available in React 16+. This likely ' +
70 + 'means you have multiple copies of React and are attempting to nest ' +
71 + 'a React 15 tree inside a React 16 tree using ' +
72 + "unstable_renderSubtreeIntoContainer, which isn't supported. Try " +
73 + 'to make sure you have only one copy of React (and ideally, switch ' +
74 + 'to ReactDOM.unstable_createPortal).',
75 + );
76 + },
77 + });
78 + Object.freeze(fakeInternalInstance);
79 }
80
81 module.exports = function(
@@ -283,6 +305,9 @@ module.exports = function(
305 workInProgress.stateNode = instance;
306 // The instance needs access to the fiber so that it can schedule updates
307 ReactInstanceMap.set(instance, workInProgress);
308 + if (__DEV__) {
309 + instance._reactInternalInstance = fakeInternalInstance;
310 + }
311 }
312
313 function constructClassInstance(workInProgress: Fiber, props: any): any {
src/renderers/shared/shared/ReactInstanceMap.js
+4 -4
@@ -26,19 +26,19 @@ var ReactInstanceMap = {
26 * supported we can rename it.
27 */
28 remove: function(key) {
29 - key._reactInternalInstance = undefined;
29 + key._reactInternalFiber = undefined;
30 },
31
32 get: function(key) {
33 - return key._reactInternalInstance;
33 + return key._reactInternalFiber;
34 },
35
36 has: function(key) {
37 - return key._reactInternalInstance !== undefined;
37 + return key._reactInternalFiber !== undefined;
38 },
39
40 set: function(key, value) {
41 - key._reactInternalInstance = value;
41 + key._reactInternalFiber = value;
42 },
43 };
44