Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to do flow type annotations for React hooks (useState, etc.)?

How should we be using Flow type annotations with react hooks, such as useState? I've tried searching for some examples of how they should be implemented, but can't find anything.

I tried this:

const [allResultsVisible, setAllResultsVisible]: [ boolean, (boolean) => void, ] = useState(false);

Which doesn't throw any flow related errors, but I'm not sure if this is correct or the best way to annotate the hook. If my attempt isn't correct or the best way, what should I do instead?

like image 955
timothym Avatar asked May 03 '19 22:05

timothym


People also ask

How do you set type useState in React?

To define a type for React. useState() you must add a <type> after typing the word useState and before the opening parenthesis. This will tell TypeScript that you're giving a specific type to state property variable.

What is the useState () method in React?

The React useState Hook allows us to track state in a function component. State generally refers to data or properties that need to be tracking in an application.

What is the use of useState () in Hook?

useState is a Hook that allows you to have state variables in functional components. You pass the initial state to this function and it returns a variable with the current state value (not necessarily the initial state) and another function to update this value.

What is useState and useEffect hooks in React?

The useState hook is used for storing variables that are part of your application's state and will change as the user interacts with your website. The useEffect hook allows components to react to lifecycle events such as mounting to the DOM, re-rendering, and unmounting.


3 Answers

Flow infers the types, as shown in the PR that added support for hooks to the Flow library.

UPDATE

As discussed in my comments of another answer, the resulting variables must be used contextually for the type-checking to work as expected.

const [loading, setLoading] = React.useState(true);
(loading: boolean);

setLoading('foo') // Flow error

vs.

const [loading, setLoading] = React.useState(true);

setLoading('foo') // no Flow error
like image 172
Andrew Smith Avatar answered Sep 27 '22 08:09

Andrew Smith


Type inferring doesn't work for me:

const [loading, setLoading] = React.useState(true) // boolean
setLoading('foo') // no Flow error
setLoading(1) // no Flow error

Had to add typings manually:

const [loading, setLoading]: [boolean, ((boolean => boolean) | boolean) => void] = React.useState(false)
setLoading('foo') // Flow error
setLoading(1) // Flow error

I have:

"react": "16.8.6",
"flow-bin": "0.100.0",

UPDATE

As @AndrewSouthpaw pointed, loading has to be used in some context or setLoading won't work correctly.

This works:

const [loading, setLoading] = React.useState(true);
(loading: boolean);

setLoading('foo'); // Flow error

The same without semicolons:

 const [loading, setLoading] = React.useState(true)
 ;(loading: boolean)

 setLoading('foo') // Flow error

ESLint

ESLint no-unused-expressions will give an error from this. eslint-plugin-flowtype has fixed version flowtype/no-unused-expressions.

like image 21
Archinowsk Avatar answered Sep 26 '22 08:09

Archinowsk


If the type can be inferred from the initial value, no need to add typing information for Flow, for example:

const [open, setOpen] = React.useState(false);

If it can't be inferred because the initial value is a complex object, use generics to assign a type, for example:

type Merchandize = {|
  name: string,
  value: number,
|};

const [shoppingCare, setShoppingCart] = React.useState<Array<Merchandize>>([]);
like image 35
Cat Chen Avatar answered Sep 26 '22 08:09

Cat Chen