diff --git a/src/handlers/__tests__/__snapshots__/defaultPropsHandler-test.js.snap b/src/handlers/__tests__/__snapshots__/defaultPropsHandler-test.js.snap
index f7c4a11a2a8..112236db3c2 100644
--- a/src/handlers/__tests__/__snapshots__/defaultPropsHandler-test.js.snap
+++ b/src/handlers/__tests__/__snapshots__/defaultPropsHandler-test.js.snap
@@ -226,6 +226,28 @@ Object {
}
`;
+exports[`defaultPropsHandler forwardRef resolves default props in the parameters 1`] = `
+Object {
+ "foo": Object {
+ "defaultValue": Object {
+ "computed": false,
+ "value": "'bar'",
+ },
+ },
+}
+`;
+
+exports[`defaultPropsHandler forwardRef resolves defaultProps 1`] = `
+Object {
+ "foo": Object {
+ "defaultValue": Object {
+ "computed": false,
+ "value": "'baz'",
+ },
+ },
+}
+`;
+
exports[`defaultPropsHandler should only consider Property nodes, not e.g. spread properties 1`] = `
Object {
"bar": Object {
diff --git a/src/handlers/__tests__/defaultPropsHandler-test.js b/src/handlers/__tests__/defaultPropsHandler-test.js
index fc9009c8a12..e84c78bc60b 100644
--- a/src/handlers/__tests__/defaultPropsHandler-test.js
+++ b/src/handlers/__tests__/defaultPropsHandler-test.js
@@ -219,4 +219,28 @@ describe('defaultPropsHandler', () => {
expect(documentation.descriptors).toMatchSnapshot();
});
});
+
+ describe('forwardRef', () => {
+ it('resolves default props in the parameters', () => {
+ const src = `
+ import React from 'react';
+ React.forwardRef(({ foo = 'bar' }, ref) =>
{foo}
);
+ `;
+ defaultPropsHandler(
+ documentation,
+ parse(src).get('body', 1, 'expression'),
+ );
+ expect(documentation.descriptors).toMatchSnapshot();
+ });
+
+ it('resolves defaultProps', () => {
+ const src = `
+ import React from 'react';
+ const Component = React.forwardRef(({ foo }, ref) => {foo}
);
+ Component.defaultProps = { foo: 'baz' };
+ `;
+ defaultPropsHandler(documentation, parse(src).get('body', 1));
+ expect(documentation.descriptors).toMatchSnapshot();
+ });
+ });
});
diff --git a/src/handlers/defaultPropsHandler.js b/src/handlers/defaultPropsHandler.js
index 1988758a121..a517ccb71f4 100644
--- a/src/handlers/defaultPropsHandler.js
+++ b/src/handlers/defaultPropsHandler.js
@@ -15,7 +15,8 @@ import printValue from '../utils/printValue';
import recast from 'recast';
import resolveToValue from '../utils/resolveToValue';
import resolveFunctionDefinitionToReturnValue from '../utils/resolveFunctionDefinitionToReturnValue';
-import isStatelessComponent from '../utils/isStatelessComponent';
+import isReactComponentClass from '../utils/isReactComponentClass';
+import isReactForwardRefCall from '../utils/isReactForwardRefCall';
const {
types: { namedTypes: types },
@@ -53,7 +54,12 @@ function getDefaultValue(path: NodePath) {
}
function getStatelessPropsPath(componentDefinition): NodePath {
- return resolveToValue(componentDefinition).get('params', 0);
+ const value = resolveToValue(componentDefinition);
+ if (isReactForwardRefCall(value)) {
+ const inner = value.get('arguments', 0);
+ return inner.get('params', 0);
+ }
+ return value.get('params', 0);
}
function getDefaultPropsPath(componentDefinition: NodePath): ?NodePath {
@@ -118,7 +124,10 @@ export default function defaultPropsHandler(
) {
let statelessProps = null;
const defaultPropsPath = getDefaultPropsPath(componentDefinition);
- if (isStatelessComponent(componentDefinition)) {
+ /**
+ * function, lazy, memo, forwardRef etc components can resolve default props as well
+ */
+ if (!isReactComponentClass(componentDefinition)) {
statelessProps = getStatelessPropsPath(componentDefinition);
}