Skip to content

Commit c01d1a0

Browse files
committed
Fix detecting super class in react class components
1 parent 82154c3 commit c01d1a0

File tree

3 files changed

+55
-16
lines changed

3 files changed

+55
-16
lines changed

Diff for: .changeset/eight-coats-tie.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'react-docgen': patch
3+
---
4+
5+
Fix detection of react class components when super class is imported via named
6+
import.

Diff for: packages/react-docgen/src/utils/__tests__/isReactComponentClass-test.ts

+33-4
Original file line numberDiff line numberDiff line change
@@ -31,23 +31,25 @@ describe('isReactComponentClass', () => {
3131
});
3232

3333
test('ignores static render methods', () => {
34-
const def = parse.statement('class Foo { static render() {}}');
34+
const def = parse.statement('class Foo extends X { static render() {}}');
3535

3636
expect(isReactComponentClass(def)).toBe(false);
3737
});
3838

3939
test('ignores dynamic render methods', () => {
40-
const def = parse.statement('class Foo { static [render]() {}}');
40+
const def = parse.statement(
41+
'class Foo extends X { static [render]() {}}',
42+
);
4143

4244
expect(isReactComponentClass(def)).toBe(false);
4345
});
4446

4547
test('ignores getter or setter render methods', () => {
46-
let def = parse.statement('class Foo { get render() {}}');
48+
let def = parse.statement('class Foo extends X { get render() {}}');
4749

4850
expect(isReactComponentClass(def)).toBe(false);
4951

50-
def = parse.statement('class Foo { set render(value) {}}');
52+
def = parse.statement('class Foo extends X { set render(value) {}}');
5153
expect(isReactComponentClass(def)).toBe(false);
5254
});
5355
});
@@ -86,6 +88,33 @@ describe('isReactComponentClass', () => {
8688
expect(isReactComponentClass(def)).toBe(true);
8789
});
8890

91+
test('resolves the super class reference with named import', () => {
92+
const def = parse.statementLast(`
93+
import { Component } from 'react';
94+
class Foo extends Component {}
95+
`);
96+
97+
expect(isReactComponentClass(def)).toBe(true);
98+
});
99+
100+
test('resolves the super class reference with default import', () => {
101+
const def = parse.statementLast(`
102+
import React from 'react';
103+
class Foo extends React.Component {}
104+
`);
105+
106+
expect(isReactComponentClass(def)).toBe(true);
107+
});
108+
109+
test('resolves the super class reference with namespace import', () => {
110+
const def = parse.statementLast(`
111+
import * as React from 'react';
112+
class Foo extends React.Component {}
113+
`);
114+
115+
expect(isReactComponentClass(def)).toBe(true);
116+
});
117+
89118
test('resolves the super class reference with alias', () => {
90119
const def = parse.statementLast(`
91120
var { Component: C } = require('react');

Diff for: packages/react-docgen/src/utils/isReactComponentClass.ts

+16-12
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import isReactModuleName from './isReactModuleName.js';
88
import resolveToModule from './resolveToModule.js';
99
import resolveToValue from './resolveToValue.js';
1010
import isDestructuringAssignment from './isDestructuringAssignment.js';
11+
import isImportSpecifier from './isImportSpecifier.js';
1112

1213
function isRenderMethod(path: NodePath): boolean {
1314
if (
@@ -35,19 +36,24 @@ function classExtendsReactComponent(path: NodePath): boolean {
3536
const property = path.get('property');
3637

3738
if (
38-
!property.isIdentifier({ name: 'Component' }) &&
39-
!property.isIdentifier({ name: 'PureComponent' })
39+
property.isIdentifier({ name: 'Component' }) ||
40+
property.isIdentifier({ name: 'PureComponent' })
4041
) {
41-
return false;
42+
return true;
4243
}
4344
} else if (
44-
!isDestructuringAssignment(path, 'Component') &&
45-
!isDestructuringAssignment(path, 'PureComponent')
45+
isImportSpecifier(path, 'Component') ||
46+
isImportSpecifier(path, 'PureComponent')
4647
) {
47-
return false;
48+
return true;
49+
} else if (
50+
isDestructuringAssignment(path, 'Component') ||
51+
isDestructuringAssignment(path, 'PureComponent')
52+
) {
53+
return true;
4854
}
4955

50-
return true;
56+
return false;
5157
}
5258

5359
/**
@@ -61,11 +67,6 @@ export default function isReactComponentClass(
6167
return false;
6268
}
6369

64-
// extends something
65-
if (!path.node.superClass) {
66-
return false;
67-
}
68-
6970
// React.Component or React.PureComponent
7071
const superClass = path.get('superClass');
7172

@@ -79,6 +80,9 @@ export default function isReactComponentClass(
7980
return true;
8081
}
8182
}
83+
} else {
84+
// does not extend anything
85+
return false;
8286
}
8387

8488
// render method

0 commit comments

Comments
 (0)