@samitouri / QOS-React-2 / commits / 0752a63f59

add Portal support to React.Children calls (#11378)

Matteo Vesprini-Heidrich committed Oct 31, 2017 at 10:59 UTC 0752a63f59168b56b14ec45220bad97b39222604
2 files changed +30 -2
packages/react/src/ReactChildren.js
+5 -2
@@ -25,7 +25,9 @@ var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.
25 var REACT_ELEMENT_TYPE =
26 (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) ||
27 0xeac7;
28 -
28 +const REACT_PORTAL_TYPE =
29 + (typeof Symbol === 'function' && Symbol.for && Symbol.for('react.portal')) ||
30 + 0xeaca;
31 var SEPARATOR = '.';
32 var SUBSEPARATOR = ':';
33
@@ -125,7 +127,8 @@ function traverseAllChildrenImpl(
127 type === 'number' ||
128 // The following is inlined from ReactElement. This means we can optimize
129 // some checks. React Fiber also inlines this logic for similar purposes.
128 - (type === 'object' && children.$$typeof === REACT_ELEMENT_TYPE)
130 + (type === 'object' && children.$$typeof === REACT_ELEMENT_TYPE) ||
131 + (type === 'object' && children.$$typeof === REACT_PORTAL_TYPE)
132 ) {
133 callback(
134 traverseContext,
packages/react/src/__tests__/ReactChildren-test.js
+25
@@ -48,6 +48,31 @@ describe('ReactChildren', () => {
48 expect(mappedChildren[0]).toEqual(<span key=".$simple" />);
49 });
50
51 + it('should support Portal components', () => {
52 + const context = {};
53 + const callback = jasmine.createSpy().and.callFake(function(kid, index) {
54 + expect(this).toBe(context);
55 + return kid;
56 + });
57 + const ReactDOM = require('react-dom');
58 + const portalContainer = document.createElement('div');
59 +
60 + const simpleChild = <span key="simple" />;
61 + const portal = ReactDOM.createPortal(simpleChild, portalContainer);
62 + const instance = <div>{portal}</div>;
63 +
64 + React.Children.forEach(instance.props.children, callback, context);
65 + expect(callback).toHaveBeenCalledWith(portal, 0);
66 + callback.calls.reset();
67 + const mappedChildren = React.Children.map(
68 + instance.props.children,
69 + callback,
70 + context,
71 + );
72 + expect(callback).toHaveBeenCalledWith(portal, 0);
73 + expect(mappedChildren[0]).toEqual(portal);
74 + });
75 +
76 it('should treat single arrayless child as being in array', () => {
77 var context = {};
78 var callback = jasmine.createSpy().and.callFake(function(kid, index) {