React Hooks - JSDoc with destructured array variables
Asked Answered
M

4

14

I'm trying to JSDoc a simple React Typescript component with hooks. Unfortunately, I can't seem to find a way that makes JSDoc work with declared destructured arrays. There are some answers related to destructuring object params, but these don't work for arrays.

/**
 * @property {boolean} 0 - documentation for isLoading
 * @property {func} 1 - documentation for setIsLoading
 */
 const [isLoading, setIsLoading] = React.useState<boolean>(false);

Update 1: Still having trouble finding a way to document this destructure. There is a corner case where if I custom type an object, it works:

export type AuthFormInput = {
  /** Value of the Email input field */
  email: string;
  /** Value of the Password input field */
  password: string;
};

const [form, setForm] = React.useState<AuthFormInput>({
  email: '',
  password: ''
});

...

// JSDoc will work here
const email = form.email;
Merola answered 17/9, 2019 at 14:12 Comment(4)
Did you post all the relevant code? I don't see any reference to JSDoc or a destructured array.Unthoughtof
@RutherfordWonkington JSDoc is indeed the comment block above the single line of code. The destructured array is in const [isLoading, setIsLoading].Merola
so you want to JSDoc local variable, am I right? if yes, what's the need?Seringa
@Seringa mainly to document the component state so that the reference to it can be brought up later when it's used.Merola
H
29

It would help:

    /**
     * @typedef {Boolean} LoadingState — documentation for isLoading
     * @description Additional doc
     */
    /**
     * @typedef {Function} LoadingStateSetter — documentation for setIsLoading
     */
    /**
     * @type {[LoadingState, LoadingStateSetter]} Loading
     */
    const [isLoading, setIsLoading] = React.useState();

In this example we declare two additional types: LoadingState and LoadingStateSetter. Then we add some description for them and finally, we declare the Loading type for the result of React.useState()

You also can declare it in a more simple way like this:

    /**
      * @type {[Boolean, Function]} Loading
      */
    const [isLoading, setIsLoading] = React.useState();

But I didn't find a way to add a description in this case.

I've checked the description of such way of documentation in VSCode

Hotbed answered 25/9, 2019 at 20:17 Comment(0)
C
8

You can try this:

/** @type {boolean} */
const initialState = false
const [isLoading, setIsLoading] = React.useState(initialState)
Chilli answered 29/12, 2020 at 6:15 Comment(2)
this is better because typescript would infer the type of isLoading and setIsLoading by itself +1. setIsLoading is more complex than Function, it is React.Dispatch<React.SetStateAction<boolean>>Raceway
Note that this only work if there is one type that the variable can hold - meaning that if you wanted a nullable value for example, it will infer only a partial type (even if you specific the type for the variable). Kind of annoying to be honest...Sinistrodextral
E
7

The actual best solution to be found here is by using parentheses. Otherwise jsdoc does not seem to catch it:

const [authFormInput, setAuthFormInput] = useState(/** @type {AuthFormInput} */({..}));
Epidemiology answered 3/11, 2021 at 7:36 Comment(1)
this is the simplest and the best solutionAnagoge
N
1

The cleanest way I found is to use types.d.ts, since we're likely gonna need to type out more than just a useState and we can keep a lot of the code there for cleanliness:

// types.d.ts:
declare type State = string;
declare type SetState = (stateParam: State) => void;
declare type UseState = [State, SetState];

// component.jsx:
  /**
   * @type {UseState}
  */
  const [state, setstate] = useState("");
Nevsa answered 19/1, 2022 at 14:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.