Skip to main content

Function/Class Components

Adding Flow types to your React components is incredibly powerful. After typing your component, Flow will statically ensure that you are using the component in the way it was designed to be used.

Functional Components

Adding Flow types to a functional component is the same as adding types to a standard function. Just create an object type for the props and Flow will ensure that the props passed to the component match up with what is expected.

1import React from 'react';2
3type Props = {4  foo: number,5  bar?: string,6};7
8function MyComponent(props: Props) {9  props.doesNotExist; // Error! You did not define a `doesNotExist` prop.
10 11 return <div>{props.bar}</div>;12}13 14<MyComponent foo={42} />
9:9-9:20: Cannot get `props.doesNotExist` because property `doesNotExist` is missing in `Props` [1]. [prop-missing]

Adding Default Props to Functional Components

A nice pattern to add default props to functional components is to use destructuring with default values. By destructuring the props in the function parameter, you can assign a value to any props that are not passed to the component (or passed with the value undefined).

1import React from 'react';2
3type Props = {4  foo?: number, // foo is optional to pass in.5  bar: string, // bar is required.6};7
8function MyComponent({foo = 42, bar}: Props) {9  // Flow knows that foo is not null or undefined10  const baz = foo + 1;11}12
13// And we don't need to include foo.14<MyComponent bar={"abc"} />;

Class Components

To Flowify a class component, the type of the props can be passed as the first argument to the React.Component type. This will have the same effect as adding types to the props parameter of a function component.

1import React from 'react';2
3type Props = {4  foo: number,5  bar?: string,6};7
8class MyComponent extends React.Component<Props> {9  render(): React.Node {10    this.props.doesNotExist; // Error! You did not define a `doesNotExist` prop.
11 12 return <div>{this.props.bar}</div>;13 }14}15 16<MyComponent foo={42} />;
10:16-10:27: Cannot get `this.props.doesNotExist` because property `doesNotExist` is missing in `Props` [1]. [prop-missing]

Now wherever we use this.props in our React component Flow will treat it as the Props type we defined.

Note: If you don't need to use the Props type again you could also define it inline: extends React.Component<{ foo: number, bar?: string }>.

React.Component<Props, State> is a generic type that takes two type arguments: props and state. The second type argument, State, is optional. By default it is undefined so you can see in the example above we did not include State. We will learn more about state in the next section...

Adding State

To add a type for state to your React class component: create a new object type, in the example below we name it State, and pass it as the second type argument to React.Component.

1import React from 'react';2
3type Props = { /* ... */ };4
5type State = {6  count: number,7};8
9class MyComponent extends React.Component<Props, State> {10  state: State = {11    count: 0,12  };13
14  componentDidMount() {15    setInterval(() => {16      this.setState(prevState => ({17        count: prevState.count + 1,18      }));19    }, 1000);20  }21
22  render(): React.Node {23    return <div>Count: {this.state.count}</div>;24  }25}26
27<MyComponent />;

In the example above we are using a React setState() updater function but you could also pass a partial state object to setState().

Note: If you don't need to use the State type again you could also define it inline: extends React.Component<{}, { count: number }>.

Using Default Props for Class Components

React supports the notion of defaultProps which you can think of as default function arguments. When you create an element and do not include a prop which has a default then React will substitute that prop with its corresponding value from defaultProps. Flow supports this notion as well. To type default props add a static defaultProps property to your class.

1import React from 'react';2
3type Props = {4  foo: number, // foo is required.5  bar: string, // bar is required.6};7
8class MyComponent extends React.Component<Props> {9  static defaultProps: {foo: number} = {10    foo: 42, // ...but we have a default prop for foo.11  };12}13
14// So we don't need to include foo.15<MyComponent bar={"abc"} />

Note: You don't need to make foo nullable in your Props type. Flow will make sure that foo is optional if you have a default prop for foo.

If you add a type annotation to defaultProps you can define the type as

1type DefaultProps = {2  foo: number,3};

and spread that into the Props type:

type Props = {
...DefaultProps,
bar: string,
};

This way you avoid duplicating the properties that happen to have a default value.

Note: You can also apply this format of default props to functional components by adding a defaultProps property to a the component function. However, it is generally simpler to use the destructuring pattern described above.

1function MyComponent(props: {foo: number}) {}2MyComponent.defaultProps = {foo: 42};