Docz: PropsTable is not working with components encapsulated by React.forwardRef()

Created on 14 Sep 2018  路  9Comments  路  Source: doczjs/docz

<PropsTable of={Input} /> only works when I remove the React.forwardRef(). The following code is Typescript, and I also have typescript: true on my config.

import * as React from "react"
import styled from "styled-components"

// Estilos ---------------------------------------------------------------------

const StyledInput = styled.input.attrs({
  className: "form-control",
})`
  height: 40px;
  margin-bottom: 0;
  font-size: 0.8125rem;
`

const FormRow = styled.div.attrs({
  className: "form-group",
})`
  margin-bottom: 1.25rem;
`

// <Input /> -------------------------------------------------------------------

interface IPInput {
  id: string
  label?: string | false
  placeholder?: string
}

const Input = React.forwardRef(
  (
    { id, label, placeholder, ...extraProps }: IPInput,
    ref: React.RefObject<HTMLInputElement>,
  ) => (
    <FormRow>
      <label
        htmlFor={id}
        className={[false === label ? "sr-only" : ""].join(" ")}
      >
        {false === label && placeholder ? placeholder : label}
      </label>
      <StyledInput
        innerRef={ref}
        id={id}
        placeholder={placeholder}
        {...extraProps}
      />
    </FormRow>
  ),
)

export default Input

bug

Most helpful comment

I think that this will be fixed in the v1 :v:

All 9 comments

I have found a solution but it looks ugly.

// ./MyComponent.js

const WrappedComponent = React.forwardRef(
  function MyComponent(props, ref) {
    return <StyledComponent innerRef={ref} {...props} />;
  }
);

or

// ./MyComponent.js

const MyComponent = (props, ref) => (
  <StyledComponent innerRef={ref} {...props} />;
);

export default React.forwardRef(MyComponent);
// ./MyComponent.mdx

<PropsTable of={WrappedComponent.render} />

@sandiiarov innerRef has been deprecated in styled-components. forwardRef is what will need to be used in the future.

@Jared-Dev Yeah I know. It doesn't matter in that example.

It looks like as soon as your component is wrapped inside a HOC, it won't render the prop types. Quickest solution for now is to also export your component as a named export without the HOCs. That way your prop types will work again.

Hi

PropsTable uses __docgenInfo's data. you do not have access to it in a HOC but in the wrapped component. You have to give the wrapped component to <PropsTable>

2 solutions :

  • import both component and wrapped component (you have to export wrapped component). Use the wrapped component to display <PropsTable>
// ./MyComponent.js
export const MyComponent = ...;
export default MyHoc(MyComponent);

// ./MyComponent.mdx
import MyComponent, {MyComponent as MyComponentWithPropTypes} from './MyComponent'
<Playground><MyComponent /></Playground>
<PropsTable of={MyComponentWithPropTypes} />
  • use render().type to access to wrapped component via hoc
// ./MyComponent.js
const MyComponent = ...;
export default MyHoc(MyComponent);

// ./MyComponent.mdx
import MyComponent from './MyComponent'
<Playground><MyComponent /></Playground>
<PropsTable of={MyComponent.render().type} />

By default MyComponent.render().type does not have __docgenInfo.
__docgenInfo is generated by babel-plugin-react-docgen and the default value of the resolver option (findAllExportedComponentDefinition) doesn't create the __docgenInfo if the component is not exported. You should use findAllComponentDefinitions value.
See https://github.com/storybooks/babel-plugin-react-docgen#babelrc-options for more info.

Otherwise you should export the wrapped component (like in the first solution) to have access to __docgenInfo.

@jnaudin Thanks for posting such detailed solutions. The first one works great, but the second one I got MyComponent.render is not a function error. Any ideas?

I think that this will be fixed in the v1 :v:

@jnaudin Thanks for posting such detailed solutions. The first one works great, but the second one I got MyComponent.render is not a function error. Any ideas?

I think you imported the wrapped component and not the HOC:
import {MyComponent} from './MyComponent'
instead of
import MyComponent from './MyComponent'

Can you show me what your code ?

Closed in favor of the newest release.

Was this page helpful?
0 / 5 - 0 ratings