diff --git a/.changeset/young-carrots-sort.md b/.changeset/young-carrots-sort.md new file mode 100644 index 00000000000..2845729d591 --- /dev/null +++ b/.changeset/young-carrots-sort.md @@ -0,0 +1,5 @@ +--- +'react-docgen': patch +--- + +Fix detection of React.Children with ESM imports diff --git a/packages/react-docgen/src/utils/__tests__/isReactChildrenElementCall-test.ts b/packages/react-docgen/src/utils/__tests__/isReactChildrenElementCall-test.ts index f1cb22bacc9..c1b71074ca4 100644 --- a/packages/react-docgen/src/utils/__tests__/isReactChildrenElementCall-test.ts +++ b/packages/react-docgen/src/utils/__tests__/isReactChildrenElementCall-test.ts @@ -21,6 +21,42 @@ describe('isReactChildrenElementCall', () => { expect(isReactChildrenElementCall(def)).toBe(true); }); + + test('React.Children.only without React', () => { + const def = parse.expressionLast(` + var Children = require("React").Children; + Children.only(() => {}); + `); + + expect(isReactChildrenElementCall(def)).toBe(true); + }); + + test('React.Children.only with destructuring', () => { + const def = parse.expressionLast(` + var { Children } = require("React"); + Children.only(() => {}); + `); + + expect(isReactChildrenElementCall(def)).toBe(true); + }); + + test('React.Children.only with import', () => { + const def = parse.expressionLast(` + import React from 'react'; + React.Children.only(() => {}); + `); + + expect(isReactChildrenElementCall(def)).toBe(true); + }); + + test('React.Children.only with named import', () => { + const def = parse.expressionLast(` + import { Children } from 'react'; + Children.only(() => {}); + `); + + expect(isReactChildrenElementCall(def)).toBe(true); + }); }); describe('false', () => { test('not call expression', () => { diff --git a/packages/react-docgen/src/utils/isReactChildrenElementCall.ts b/packages/react-docgen/src/utils/isReactChildrenElementCall.ts index 4c22fdb012a..543ed9e246c 100644 --- a/packages/react-docgen/src/utils/isReactChildrenElementCall.ts +++ b/packages/react-docgen/src/utils/isReactChildrenElementCall.ts @@ -1,7 +1,6 @@ import type { NodePath } from '@babel/traverse'; -import isReactModuleName from './isReactModuleName.js'; -import resolveToModule from './resolveToModule.js'; import type { CallExpression } from '@babel/types'; +import isReactBuiltinReference from './isReactBuiltinReference.js'; /** * Returns true if the expression is a function call of the form @@ -16,24 +15,16 @@ export default function isReactChildrenElementCall( const callee = path.get('callee'); - if ( - !callee.isMemberExpression() || - (!callee.get('property').isIdentifier({ name: 'only' }) && - !callee.get('property').isIdentifier({ name: 'map' })) - ) { - return false; - } - - const calleeObj = callee.get('object'); + if (callee.isMemberExpression()) { + const calleeProperty = callee.get('property'); - if ( - !calleeObj.isMemberExpression() || - !calleeObj.get('property').isIdentifier({ name: 'Children' }) - ) { - return false; + if ( + calleeProperty.isIdentifier({ name: 'only' }) || + calleeProperty.isIdentifier({ name: 'map' }) + ) { + return isReactBuiltinReference(callee.get('object'), 'Children'); + } } - const module = resolveToModule(calleeObj); - - return Boolean(module && isReactModuleName(module)); + return false; }