Skip to content

Commit 522e8f5

Browse files
mfazekasdanez
andcommitted
fix: Fix wrong detection of forwardRef in combination with memo (#592)
Co-authored-by: Daniel Tschinder <[email protected]>
1 parent 09832a2 commit 522e8f5

File tree

7 files changed

+42
-6
lines changed

7 files changed

+42
-6
lines changed

src/__tests__/__snapshots__/main-test.js.snap

+16
Original file line numberDiff line numberDiff line change
@@ -1595,3 +1595,19 @@ Object {
15951595
},
15961596
}
15971597
`;
1598+
1599+
exports[`main fixtures processes component "component_42.js" without errors 1`] = `
1600+
Object {
1601+
"description": "",
1602+
"methods": Array [],
1603+
"props": Object {
1604+
"foo": Object {
1605+
"defaultValue": Object {
1606+
"computed": false,
1607+
"value": "'bar'",
1608+
},
1609+
"required": false,
1610+
},
1611+
},
1612+
}
1613+
`;
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import React, {memo, forwardRef} from 'react';
2+
3+
export default memo(forwardRef(({ foo = 'bar' }, ref) => <div ref={ref}>{foo}</div>));

src/handlers/__tests__/componentDocblockHandler-test.js

+7
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,13 @@ describe('componentDocblockHandler', () => {
245245
);
246246
});
247247

248+
describe('inline implementation with memo', () => {
249+
test(`
250+
React.memo(React.forwardRef((props, ref) => {}));
251+
import React from "react";`, src =>
252+
beforeLastStatement(src).get('expression'));
253+
});
254+
248255
describe('out of line implementation', () => {
249256
test(
250257
[

src/handlers/defaultPropsHandler.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ function getDefaultValue(path: NodePath) {
4949
}
5050

5151
function getStatelessPropsPath(componentDefinition): NodePath {
52-
const value = resolveToValue(componentDefinition);
52+
let value = resolveToValue(componentDefinition);
5353
if (isReactForwardRefCall(value)) {
54-
const inner = resolveToValue(value.get('arguments', 0));
55-
return inner.get('params', 0);
54+
value = resolveToValue(value.get('arguments', 0));
5655
}
56+
5757
return value.get('params', 0);
5858
}
5959

src/utils/__tests__/isReactForwardRefCall-test.js

+8
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,14 @@ describe('isReactForwardRefCall', () => {
7878
expect(isReactForwardRefCall(def)).toBe(true);
7979
});
8080

81+
it('does not accept forwardRef if not outer call', () => {
82+
const def = parsePath(`
83+
import { forwardRef, memo } from "react";
84+
memo(forwardRef({}));
85+
`);
86+
expect(isReactForwardRefCall(def)).toBe(false);
87+
});
88+
8189
it('accepts forwardRef called on imported aliased value', () => {
8290
const def = parsePath(`
8391
import { forwardRef as foo } from "react";

src/utils/isReactBuiltinCall.js

+4-1
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,13 @@ export default function isReactBuiltinCall(
4242
// `import { createElement } from 'react'`
4343
(t.ImportDeclaration.check(value.node) &&
4444
value.node.specifiers.some(
45-
specifier => specifier.imported && specifier.imported.name === name,
45+
specifier =>
46+
specifier.imported?.name === name &&
47+
specifier.local?.name === path.node.callee.name,
4648
))
4749
) {
4850
const module = resolveToModule(value);
51+
4952
return Boolean(module && isReactModuleName(module));
5053
}
5154
}

src/utils/isReactCreateClassCall.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
*/
99

1010
import { namedTypes as t } from 'ast-types';
11-
import match from './match';
1211
import resolveToModule from './resolveToModule';
1312
import isReactBuiltinCall from './isReactBuiltinCall';
1413

@@ -24,7 +23,7 @@ function isReactCreateClassCallModular(path: NodePath): boolean {
2423
path = path.get('expression');
2524
}
2625

27-
if (!match(path.node, { type: 'CallExpression' })) {
26+
if (!t.CallExpression.check(path.node)) {
2827
return false;
2928
}
3029
const module = resolveToModule(path);

0 commit comments

Comments
 (0)