Search code examples
reactjsreact-hooksjsdocreact-ref

How to create a JSDoc of ref when using React.fowardRef and useImperativeHandle?


I'm not using typescript in my reactjs project, but I still want to document my components with JSDocs.

The problem where is that I have a functional component with React.forwardRef and I want to create a JSDoc to the ref because I'm using useImperativeHandle and passing different values to the ref.

It's possible to document the ref using JSDoc to display the methods and properties that I pass in useImperativeHandle? If yes, how?

Where is an example of what I want

In a component I use React.fowardRef with useImperativeHandle

export const Foo = React.fowardRef((props, ref) => {

    useImperativeHandle(ref, () => ({
        myMethod,
        // other methods and properties
    }))

    return <div>{/* ... */}</div>
}

And when using the ref for that component with fooRef.current, I want to see myMethod or the other properties when I type . or press Ctrl+ Space.


Solution

  • While I don't know if this is the perfect solution, what worked for me was simply writing a typedef for all the props (including ref), and then passing it to @type property, all in JSDoc. Here is a snippet that should work:

    import React from 'react';
    import PropTypes from 'prop-types';
    
    /**
     * @typedef {Object} RefType
     * @property {Object} current
     * @property {() => void} current.methodOne
     * @property {() => void} current.methodTwo
     */
    
    /**
     * @typedef {Object} Props
     * @property {RefType} ref
     * @property {string} value
     * @property {((event: React.ChangeEvent<HTMLInputElement>) => void) | undefined} onChange
     */
    
    /**
     * @type {React.FC<Props>}
     */
    export const Input = React.forwardRef((
      props, 
      /** @type {RefType} */
      ref) => {
      return <input ref={ref} onChange={props.onChange} value={props.value} />
    })
    
    Input.propTypes = {
      value: PropTypes.string.isRequired,
      onChange: PropTypes.func.isRequired,
    };
    
    Input.displayName = 'Input';
    

    So when I then use the component, here is the intellisense I get in VSCode for example: Intellisense after using said component.

    The intellisense should work in the entire project.

    EDIT: I should explain why I included PropTypes. I faced the same issue to yours, and figured out a solution, but I also needed the dev tools to preserve component name. Dev tools would instead display the React.forwardRef instead of real component name. The displayName property will do the trick to keep the original name.

    EDIT: If you need to have autocomplete inside the component itself, you can do it like image link below. I've updated the code snippet to reflect this. Autocomplete on ref argument itself.