diff --git a/src/handlers/__tests__/__snapshots__/defaultPropsHandler-test.js.snap b/src/handlers/__tests__/__snapshots__/defaultPropsHandler-test.js.snap index 8d0b2a9ce69..e0803b09162 100644 --- a/src/handlers/__tests__/__snapshots__/defaultPropsHandler-test.js.snap +++ b/src/handlers/__tests__/__snapshots__/defaultPropsHandler-test.js.snap @@ -299,6 +299,17 @@ Object { } `; +exports[`defaultPropsHandler forwardRef resolves when the function is not inline 1`] = ` +Object { + "foo": Object { + "defaultValue": Object { + "computed": false, + "value": "'bar'", + }, + }, +} +`; + 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 c03a4775429..a2e739a9066 100644 --- a/src/handlers/__tests__/defaultPropsHandler-test.js +++ b/src/handlers/__tests__/defaultPropsHandler-test.js @@ -290,5 +290,18 @@ describe('defaultPropsHandler', () => { defaultPropsHandler(documentation, parse(src).get('body', 1)); expect(documentation.descriptors).toMatchSnapshot(); }); + + it('resolves when the function is not inline', () => { + const src = ` + import React from 'react'; + const ComponentImpl = ({ foo = 'bar' }, ref) =>
{foo}
; + React.forwardRef(ComponentImpl); + `; + defaultPropsHandler( + documentation, + parse(src).get('body', 2, 'expression'), + ); + expect(documentation.descriptors).toMatchSnapshot(); + }); }); }); diff --git a/src/handlers/__tests__/flowTypeHandler-test.js b/src/handlers/__tests__/flowTypeHandler-test.js index c63f9b30cad..c05167409a5 100644 --- a/src/handlers/__tests__/flowTypeHandler-test.js +++ b/src/handlers/__tests__/flowTypeHandler-test.js @@ -8,7 +8,7 @@ jest.mock('../../Documentation'); -import { expression, statement } from '../../../tests/utils'; +import { expression, statement, parse } from '../../../tests/utils'; describe('flowTypeHandler', () => { let getFlowTypeMock; @@ -334,4 +334,39 @@ describe('flowTypeHandler', () => { `); }); }); + + describe('forwardRef', () => { + it('resolves prop type from function expression', () => { + const src = ` + import React from 'react'; + type Props = { foo: string }; + React.forwardRef((props: Props, ref) =>
{props.foo}
); + `; + flowTypeHandler(documentation, parse(src).get('body', 2, 'expression')); + expect(documentation.descriptors).toEqual({ + foo: { + flowType: {}, + required: true, + description: '', + }, + }); + }); + + it('resolves when the function is not inline', () => { + const src = ` + import React from 'react'; + type Props = { foo: string }; + const ComponentImpl = (props: Props, ref) =>
{props.foo}
; + React.forwardRef(ComponentImpl); + `; + flowTypeHandler(documentation, parse(src).get('body', 3, 'expression')); + expect(documentation.descriptors).toEqual({ + foo: { + flowType: {}, + required: true, + description: '', + }, + }); + }); + }); }); diff --git a/src/handlers/defaultPropsHandler.js b/src/handlers/defaultPropsHandler.js index 8abcfde1f0f..638f08d7781 100644 --- a/src/handlers/defaultPropsHandler.js +++ b/src/handlers/defaultPropsHandler.js @@ -51,7 +51,7 @@ function getDefaultValue(path: NodePath) { function getStatelessPropsPath(componentDefinition): NodePath { const value = resolveToValue(componentDefinition); if (isReactForwardRefCall(value)) { - const inner = value.get('arguments', 0); + const inner = resolveToValue(value.get('arguments', 0)); return inner.get('params', 0); } return value.get('params', 0); diff --git a/src/utils/getFlowTypeFromReactComponent.js b/src/utils/getFlowTypeFromReactComponent.js index fd037b10b4d..74f98b7c062 100644 --- a/src/utils/getFlowTypeFromReactComponent.js +++ b/src/utils/getFlowTypeFromReactComponent.js @@ -19,7 +19,7 @@ import resolveToValue from './resolveToValue'; function getStatelessPropsPath(componentDefinition): NodePath { const value = resolveToValue(componentDefinition); if (isReactForwardRefCall(value)) { - const inner = value.get('arguments', 0); + const inner = resolveToValue(value.get('arguments', 0)); return inner.get('params', 0); } return value.get('params', 0);