Skip to content

Commit

Permalink
feat(defaultPropsHandler): Fully support forwardRef (#350)
Browse files Browse the repository at this point in the history
* test(failing): defaultPropsHandler and forwardRef

* feat(defaultPropsHandler): support forwardRef

# Conflicts:
#	src/handlers/__tests__/__snapshots__/defaultPropsHandler-test.js.snap
  • Loading branch information
eps1lon authored and danez committed May 3, 2019
1 parent fcfb193 commit 3bb2146
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 3 deletions.
@@ -0,0 +1,23 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

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'",
},
},
}
`;
24 changes: 24 additions & 0 deletions src/handlers/__tests__/defaultPropsHandler-test.js
Expand Up @@ -219,4 +219,28 @@ describe('defaultPropsHandler', () => {
expect(documentation.descriptors).toEqual({});
});
});

describe('forwardRef', () => {
it('resolves default props in the parameters', () => {
const src = `
import React from 'react';
React.forwardRef(({ foo = 'bar' }, ref) => <div ref={ref}>{foo}</div>);
`;
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) => <div ref={ref}>{foo}</div>);
Component.defaultProps = { foo: 'baz' };
`;
defaultPropsHandler(documentation, parse(src).get('body', 1));
expect(documentation.descriptors).toMatchSnapshot();
});
});
});
15 changes: 12 additions & 3 deletions src/handlers/defaultPropsHandler.js
Expand Up @@ -18,7 +18,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 },
Expand Down Expand Up @@ -56,7 +57,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 {
Expand Down Expand Up @@ -120,7 +126,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);
}

Expand Down

0 comments on commit 3bb2146

Please sign in to comment.