Skip to content

Commit fee33bd

Browse files
Matteo Vesprini-HeidrichEthan-Arrowood
Matteo Vesprini-Heidrich
authored andcommitted
add Portal support to React.Children calls (facebook#11378)
1 parent c96feab commit fee33bd

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

packages/react/src/ReactChildren.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.
2525
var REACT_ELEMENT_TYPE =
2626
(typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) ||
2727
0xeac7;
28-
28+
const REACT_PORTAL_TYPE =
29+
(typeof Symbol === 'function' && Symbol.for && Symbol.for('react.portal')) ||
30+
0xeaca;
2931
var SEPARATOR = '.';
3032
var SUBSEPARATOR = ':';
3133

@@ -125,7 +127,8 @@ function traverseAllChildrenImpl(
125127
type === 'number' ||
126128
// The following is inlined from ReactElement. This means we can optimize
127129
// 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)
129132
) {
130133
callback(
131134
traverseContext,

packages/react/src/__tests__/ReactChildren-test.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,31 @@ describe('ReactChildren', () => {
4848
expect(mappedChildren[0]).toEqual(<span key=".$simple" />);
4949
});
5050

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+
5176
it('should treat single arrayless child as being in array', () => {
5277
var context = {};
5378
var callback = jasmine.createSpy().and.callFake(function(kid, index) {

0 commit comments

Comments
 (0)