Skip to content

Commit 6520d78

Browse files
damianfkling
authored andcommitted
Support rendering React.Children.only calls. (#169)
1 parent 51e0938 commit 6520d78

File tree

3 files changed

+72
-1
lines changed

3 files changed

+72
-1
lines changed

src/utils/__tests__/isStatelessComponent-test.js

+28
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,34 @@ describe('isStatelessComponent', () => {
9999
});
100100
});
101101

102+
describe('Stateless Function Components with React.Children.only', () => {
103+
it('accepts simple arrow function components', () => {
104+
var def = parse(`
105+
var React = require('react');
106+
var Foo = ({ children }) => React.Children.only(children, null);
107+
`).get('body', 1).get('declarations', [0]).get('init');
108+
109+
expect(isStatelessComponent(def)).toBe(true);
110+
});
111+
112+
it('accepts simple function expressions components', () => {
113+
var def = parse(`
114+
var React = require('react');
115+
let Foo = function({ children }) { return React.Children.only(children, null); };
116+
`).get('body', 1).get('declarations', [0]).get('init');
117+
118+
expect(isStatelessComponent(def)).toBe(true);
119+
});
120+
121+
it('accepts simple function declaration components', () => {
122+
var def = parse(`
123+
var React = require('react');
124+
function Foo ({ children }) { return React.Children.only(children, null); }
125+
`).get('body', 1);
126+
expect(isStatelessComponent(def)).toBe(true);
127+
});
128+
});
129+
102130
describe('Stateless Function Components inside module pattern', () => {
103131
it('', () => {
104132
var def = parse(`
+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* Copyright (c) 2015, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*
9+
* @flow
10+
*
11+
*/
12+
13+
import isReactModuleName from './isReactModuleName';
14+
import match from './match';
15+
import recast from 'recast';
16+
import resolveToModule from './resolveToModule';
17+
18+
var {types: {namedTypes: types}} = recast;
19+
20+
/**
21+
* Returns true if the expression is a function call of the form
22+
* `React.Children.only(...)`.
23+
*/
24+
export default function isReactChildrenElementCall(path: NodePath): boolean {
25+
if (types.ExpressionStatement.check(path.node)) {
26+
path = path.get('expression');
27+
}
28+
29+
if (!match(path.node, {callee: {property: {name: 'only'}}})) {
30+
return false;
31+
}
32+
33+
var calleeObj = path.get('callee', 'object');
34+
var module = resolveToModule(calleeObj);
35+
36+
if (!match(calleeObj, { value: { property: { name: 'Children' }}})) {
37+
return false;
38+
}
39+
40+
return Boolean(module && isReactModuleName(module));
41+
}

src/utils/isStatelessComponent.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import isReactComponentClass from './isReactComponentClass';
1414
import isReactCreateClassCall from './isReactCreateClassCall';
1515
import isReactCreateElementCall from './isReactCreateElementCall';
1616
import isReactCloneElementCall from './isReactCloneElementCall';
17+
import isReactChildrenElementCall from './isReactChildrenElementCall';
1718
import recast from 'recast';
1819
import resolveToValue from './resolveToValue';
1920

@@ -32,7 +33,8 @@ function isJSXElementOrReactCreateElement(path) {
3233
return (
3334
path.node.type === 'JSXElement' ||
3435
(path.node.type === 'CallExpression' && isReactCreateElementCall(path)) ||
35-
(path.node.type === 'CallExpression' && isReactCloneElementCall(path))
36+
(path.node.type === 'CallExpression' && isReactCloneElementCall(path)) ||
37+
(path.node.type === 'CallExpression' && isReactChildrenElementCall(path))
3638
);
3739
}
3840

0 commit comments

Comments
 (0)