Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 604
Vencovsky Avatar asked Jul 31 '20 17:07

Vencovsky


People also ask

How do you create refs in React?

Creating Refs Refs are created using React.createRef() and attached to React elements via the ref attribute. Refs are commonly assigned to an instance property when a component is constructed so they can be referenced throughout the component.

How do you get ref of child component React?

In child component, we create Refs by using React. createRef() and then attached to React elements via the ref attribute. // EXPLANATION: a reference to the node becomes accessible at the current attribute of the ref. In the parent component, we can get a reference to the Input component and call its focus() method.

How do you create a ref in a functional component?

To create a ref in a functional component we use the useRef() hook which returns a mutable object with a . current property set to the initialValue we passed to the hook. This returned object will persist for the full lifetime of the component. Thus, throughout all of its re-rendering and until it unmounts.


2 Answers

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.

like image 88
Sylvester Avatar answered Oct 19 '22 20:10

Sylvester


Write like:

/** @type {React.MutableRefObject<YourTypeHere>} */
const ref = useRef()

like image 2
Mir-Ismaili Avatar answered Oct 19 '22 20:10

Mir-Ismaili