Flow + React
Flow + React
Flow supports JSX and has done a lot of work internally to work great with React applications.
Setup Flow with React
Flow and Babel work well together, so it doesn’t take much to adopt as a React user. If you need to setup Babel with Flow, you can follow this guide.
Babel also works out of the box with Create React App, just install Flow and create a .flowconfig
.
Typing React with Flow
React has been designed with Flow in mind, so most things take very little effort to type properly.
Adding types for React Component props
You can replace all of your propTypes
with a simple props:
field in your component classes.
You can also specify defaultProps
as a static class property and Flow’s inference will handle the rest for you.
class MyComponent extends React.Component { props: { prop1: string, prop2: number, }; static defaultProps = { prop1: "foo" }; }
Note: You don’t have to mark your
defaultProps
as optional properties in yourprops
. Flow knows how to handle them properly.
If you cannot use a static class property for defaultProps
, you can also add a class field annotation and assign defaultProps
after the class declaration.
class MyComponent extends React.Component { static defaultProps: { prop1: string }; } MyComponent.defaultProps = { prop1: "foo" };
Adding types for React Component state
If you specify state
as a class property you can rely on inference to type it correctly.
class MyComponent extends React.Component { state = { foo: 1, bar: true, baz: 'three', }; }
If you cannot use a class property for state
, you can also add a class field annotation and assign it in the constructor.
class MyComponent extends React.Component { state: { foo: number, bar: boolean, baz: string, }; constructor(props) { super(props); this.state = { foo: 1, bar: true, baz: 'three', }; } }
Explicitly specifying React Component generics
It can sometimes be useful to explicitly specify the generics of React.Component
. You can do this by creating type aliases for your defaultProps
, props
, and state
and passing them as generics to React.Component
in that order.
type DefaultProps = { prop: string }; type Props = { prop: string }; type State = { prop: string }; class MyComponent extends React.Component<DefaultProps, Props, State> { static defaultProps = { prop: "foo" }; state = { prop: "bar" }; }
Adding types for React events
class MyComponent extends React.Component { onEvent(event: Event) { // ... } }
If you want a more specific type of event you can use one of the derived classes such as MouseEvent
.
class MyComponent extends React.Component { onMouseEvent(event: MouseEvent) { // ... } }
If you want to add the type of the element you can do so with an intersection type specifying the currentTarget
.
class MyComponent extends React.Component { onButtonEvent(event: Event & { currentTarget: HTMLButtonElement }) { // ... } }
Note: You should prefer
currentTarget
overtarget
astarget
could be any nested element due to DOM event propagation.
Adding types for React refs
All you need to do to type a ref is add a matching class field with the element type (such as HTMLElement
or HTMLButtonElement
).
import React from 'react'; class MyComponent extends React.Component { button: HTMLButtonElement; render() { return <button ref={el => this.button = el}>Toggle</button>; } }
Adding types to React lifecycle methods
React component lifecycle methods that receive props
and state
should be typed with the same types as you have provided for the component.
type Props = { /* ... */ }; type State = { /* ... */ }; class MyComponent extends React.Component<void, Props, State> { componentDidUpdate(prevProps: Props, prevState: State) { // ... } }
Adding types to React functional components
React’s functional components can be typed the same way any function can be typed in Flow.
// @flow let MyComponent = (props: { foo: string }) => { return <div>{props.foo}</div> }; let a = <MyComponent/>; // Error! let b = <MyComponent foo="bar"/>; // Works!
Building on top of object destructuring these functional components can specify default props with default values.
let MyComponent = ({ foo, bar = 2 }: { foo: number, bar?: number }) => { return <div>{foo + bar}</div>; }; let a = <MyComponent/>; // Error! let b = <MyComponent foo={42}/>; // Works! let c = <MyComponent foo={42} bar={3.14}/>; // Works!
© 2013–present Facebook Inc.
Licensed under the BSD License.
https://flow.org/en/docs/frameworks/react