react-docgen
react-docgen copied to clipboard
Doesn't find HOCs that just wrap & re-export component
Some HOCs aren't correctly parsed when they're just calling a function on an imported component. For example, exporting a HelloButton component that just exports an imported Button component wrapped in redux connect
:
hello-button.js
:
// @flow
import { connect } from 'react-redux';
import { sayHello } from '../actions/hello';
import Button from '../components/Button';
const mapStateToProps = () => ({
label: 'Say something',
});
const mapDispatchToProps = dispatch => ({
handleClick: () => {
dispatch(sayHello('Hi!!!'));
},
});
// HelloButton
export default connect(mapStateToProps, mapDispatchToProps)(Button);
button.js
:
// @flow
import React from 'react';
import './index.css';
type Props = {
label: string,
handleClick: Function
};
const Button = ({ label, handleClick }: Props) =>
<button styleName='button' onClick={handleClick}>{label}</button>
;
export default Button;
Button
is properly parsed, but HelloButton
is not considered a component, even when using the findAllComponentDefinitions
resolver.
react-docgen
only looks at files in isolation. It doesn't know that Button
inside hello-button.js
is a React component.
What would you expect the result for hello-button.js
to be? It shouldn't be difficult to write a custom resolver that finds connect
calls.
Ah, that makes more sense! I thought it did (or was supposed to do) cross-file resolution too.
Writing a resolver that finds connect
calls might not be too difficult...I'm honestly just hoping to find a documentation-generation tool that can parse my React/Flow code. Basically, just JSDoc + React/Flow parsing.
Thanks for the clarification :)
I'm having the same issue with a different type of HOC. Is there a way we could manually hint to the parser (through comment or code) that something returns a React component? Making exceptions for specific ones probably isn't sustainable, given the number of them out there (Radium, Aphrodite, Relay, recompose, react-redux, ...rest).
import { compose, withState, withHandlers } from "recompose";
const FixedComponent: Class<Component<Props, null, null>> = compose(
withState("fixed", "setFixed", false),
withHandlers({
onEnter: props => () => props.setFixed(false),
onLeave: props => () => props.setFixed(true),
}),
)(Component);
@threehams: Yeah, I just recently thought about that too. Do you have something concrete in mind?
Could use jsdoc's @type
. I'd be a little concerned about piggybacking on existing tags - would there be cases that work now, but would break with something like this? (I have very little experience with jsdoc so I'm not sure if there are major downsides here.)
/**
* Fixes the component to the top of the page after scrolling past it.
* @type React.Component
* or
* @type Component
*/
const FixedComponent: Class<Component<Props, null, null>> = compose(
// etc
It feels a bit strange to have to add a jsdoc tag when using Flow, but typing HOCs is very experimental right now.
Hi, looks like this is a deal breaker for people using recompose to create their components.
Is there any progress on this front?
@FezVrasta: Maybe https://github.com/Jmeyering/react-docgen-annotation-resolver helps you.
The general problem is that there is no standard format for HOCs. A possible solution is to write custom resolvers and handlers for specific types of HOCs, but these have to come from the community.
If you are interested in doing that for recompose, have a look at the default resolvers and handlers, and how they work. I'm also happy to answer any questions regarding this.
Isn't there any way to manually mark a function as "component"? Maybe with a comment, or a regex?
In my case I only export default
components, so I would just like react-docgen to use them all..
@FezVrasta: The resolver I linked to allows you to do that.
@FezVrasta: The resolver I linked to allows you to do that.
Do you happen to know how to use that resolver?
I'm putting this into my plugins list in .babelrc
but nothing happens:
[
"babel-plugin-react-docgen",
{
"resolver": "react-docgen-annotation-resolver",
"removeMethods": true
}
]
Of course, I tagged the component I wanted to be taken into account by react-docgen like this:
const myComponent = () => (
<h1>Component</h1>
);
/**
* @component
*/
export default withCustomHOC(myComponent);