Skip to main content

Component Syntax

Components are the foundation for building UIs in React. Component Syntax is the standard way to write them in Flow: a dedicated component primitive, enabled by default, with several advantages over plain function components:

  • Individual named params instead of a props object. Removes the destructuring-and-typing duplication of ({name}: {name: string}) and the need to wrap props in Readonly<{...}> — component params are read-only by default.
  • No return type annotation. Flow infers and enforces React.Node, and rejects components that implicitly return on any branch.
  • Optional renders clause that constrains what JSX shape the component is allowed to produce, enabling composition contracts across wrapper components and HOCs.
  • Structural rules enforced at parse/type-check time: no this, no nested component definitions, and components can only be rendered as JSX — they cannot be called as plain functions. See Rules for Components below.
  • Better support for React refs via the dedicated ref parameter position.
TypeScript comparison

component syntax is Flow-only. TypeScript models components as plain functions plus a props type. Flow's type-checker enforces rules that TypeScript's plain-function model leaves to convention or ESLint rules. See Flow's component syntax for the full comparison.

Basic Usage

You can declare a component with Component Syntax similar to how you'd declare a function:

1import * as React from 'react';2
3component Introduction(name: string, age: number) {4  return <h1>My name is {name} and I am {age} years old</h1>5}
Try

You can use a component directly in JSX: <Introduction age={9} name="Mr. Flow" />.

There are a few important details to notice here:

  1. the prop parameter names declared in the Introduction component are the same as the prop names passed to Introduction in JSX
  2. the order of the parameters in the declaration does not need to match the order that they are provided in JSX

Parameters

Children

children is the most common prop, and with Component Syntax it is just an ordinary parameter; declare it like any other. Its type is usually React.Node, which covers anything renderable (elements, strings, arrays, null, and more):

1import * as React from 'react';2
3component Card(title: string, children: React.Node) {4  return (5    <section>6      <h2>{title}</h2>7      {children}8    </section>9  );10}11
12<Card title="Welcome">13  <p>Hello!</p>14</Card>;
Try
TypeScript comparison

There is no need for a React.PropsWithChildren helper or for adding children to a props object type. children is just a parameter, and React.Node is the type to give it.

Sometimes you want children to be more specific than "anything renderable". To restrict which elements can be passed, give children a render type instead of React.Node. For example, a Menu whose children must be MenuItems can require them with renders*:

1import * as React from 'react';2
3component MenuItem(label: string) {4  return <li>{label}</li>;5}6
7component Menu(children: renders* MenuItem) {8  return <ul>{children}</ul>;9}10
11<Menu>12  <MenuItem label="Home" />13  <MenuItem label="Profile" />14</Menu>;
Try

Render Types cover the full set of constraints: renders for a single required element, renders? for an optional one, and renders* for any number of children.

String Parameters/Renaming Parameters

Components also allow you to rename parameters, which is useful when your parameter name is not a valid JavaScript identifier:

1import * as React from 'react';2
3component RenamedParameter(4  'required-renamed' as foo: number,5  'optional-renamed' as bar?: number,6  'optional-with-default-renamed' as baz?: number = 3,7) {8  foo as number; // OK9  bar as number | void; // OK10  baz as number; // OK11
12  return <div />;13}
Try

Rest Parameters

Sometimes you do not want to list out every prop explicitly because you do not intend to reference them individually in your component. This is common when you are writing a component that wraps another and need to pass props from your component to the inner one:

1import * as React from 'react';2
3// star.js4component Star(color: string, size: number) {5  return <div />;6}7type StarProps = React.PropsOf<Star>;8
9// blue_star.js10component BlueStar(...props: StarProps) {11  return <Star {...props} color="blue" />;12}
Try

Rest parameters use an object type as an annotation, which means you can use existing type utilities like object spreads and Pick to annotate more complex prop patterns:

1import * as React from 'react';2
3component OtherComponent(foo: string, bar: number) {4  return <div>{foo} {bar}</div>;5}6
7component FancyProps(8  ...props: {9    ...React.PropsOf<OtherComponent>,10    additionalProp: string,11  }12) {13  return <OtherComponent foo={props.foo} bar={props.bar} />;14}
Try

Disjoint Union Props

You can use a rest parameter with a disjoint union type to define a component that accepts one of several prop shapes. Refine the props inside the component body using the discriminant field:

1import * as React from 'react';2
3type TextProps = {kind: 'text', text: string};4type ImageProps = {kind: 'image', src: string, alt: string};5type Props = TextProps | ImageProps;6
7component MediaItem(...props: Props) {8  if (props.kind === 'text') {9    return <span>{props.text}</span>;10  } else {11    return <img src={props.src} alt={props.alt} />;12  }13}
Try

Optional Parameters and Defaults

Components allow you to declare optional parameters and specify defaults:

1import * as React from 'react';2
3component OptionalAndDefaults(4  color: string = "blue",5  extraMessage?: string,6) {7  let message = `My favorite color is ${color}.`;8  if (extraMessage != null) {9    message += `\n${extraMessage}`;