Skip to content

Commit

Permalink
add Portal support to React.Children calls (#11378)
Browse files Browse the repository at this point in the history
  • Loading branch information
Matteo Vesprini-Heidrich authored and gaearon committed Oct 31, 2017
1 parent 2b35923 commit 0752a63
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 2 deletions.
7 changes: 5 additions & 2 deletions packages/react/src/ReactChildren.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ var FAUX_ITERATOR_SYMBOL = '@@iterator'; // Before Symbol spec.
var REACT_ELEMENT_TYPE =
(typeof Symbol === 'function' && Symbol.for && Symbol.for('react.element')) ||
0xeac7;

const REACT_PORTAL_TYPE =
(typeof Symbol === 'function' && Symbol.for && Symbol.for('react.portal')) ||
0xeaca;
var SEPARATOR = '.';
var SUBSEPARATOR = ':';

Expand Down Expand Up @@ -125,7 +127,8 @@ function traverseAllChildrenImpl(
type === 'number' ||
// The following is inlined from ReactElement. This means we can optimize
// some checks. React Fiber also inlines this logic for similar purposes.
(type === 'object' && children.$$typeof === REACT_ELEMENT_TYPE)
(type === 'object' && children.$$typeof === REACT_ELEMENT_TYPE) ||
(type === 'object' && children.$$typeof === REACT_PORTAL_TYPE)
) {
callback(
traverseContext,
Expand Down
25 changes: 25 additions & 0 deletions packages/react/src/__tests__/ReactChildren-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,31 @@ describe('ReactChildren', () => {
expect(mappedChildren[0]).toEqual(<span key=".$simple" />);
});

it('should support Portal components', () => {
const context = {};
const callback = jasmine.createSpy().and.callFake(function(kid, index) {
expect(this).toBe(context);
return kid;
});
const ReactDOM = require('react-dom');
const portalContainer = document.createElement('div');

const simpleChild = <span key="simple" />;
const portal = ReactDOM.createPortal(simpleChild, portalContainer);
const instance = <div>{portal}</div>;

React.Children.forEach(instance.props.children, callback, context);
expect(callback).toHaveBeenCalledWith(portal, 0);
callback.calls.reset();
const mappedChildren = React.Children.map(
instance.props.children,
callback,
context,
);
expect(callback).toHaveBeenCalledWith(portal, 0);
expect(mappedChildren[0]).toEqual(portal);
});

it('should treat single arrayless child as being in array', () => {
var context = {};
var callback = jasmine.createSpy().and.callFake(function(kid, index) {
Expand Down

0 comments on commit 0752a63

Please sign in to comment.