> For the complete documentation index, see [llms.txt](https://jorgedacostaza.gitbook.io/typescript-pt/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://jorgedacostaza.gitbook.io/typescript-pt/tsx/react.md).

# React

> [PRO Egghead course on TypeScript and React](https://egghead.io/courses/use-typescript-to-develop-react-applications)

## Setup

Our [browser quickstart already sets you up to develop react applications](/typescript-pt/browser.md). Here are the key highlights.

* Use files with the extension `.tsx` (instead of `.ts`).
* Use `"jsx" : "react"` in your `tsconfig.json`'s `compilerOptions`.
* Install the definitions for JSX and React into your project : (`npm i -D @types/react @types/react-dom`).
* Import react into your `.tsx` files (`import * as React from "react"`).

## HTML Tags vs. Components

React can either render HTML tags (strings) or React components (classes). The JavaScript emit for these elements is different (`React.createElement('div')` vs. `React.createElement(MyComponent)`). The way this is determined is by the *case* of the *first* letter. `foo` is treated as an HTML tag and `Foo` is treated as a component.

## Type Checking

### HTML Tags

An HTML Tag `foo` is to be of the type `JSX.IntrinsicElements.foo`. These types are already defined for all the major tags in a file `react-jsx.d.ts` which we had you install as a part of the setup. Here is a sample of the the contents of the file:

```typescript
declare module JSX {
    interface IntrinsicElements {
        a: React.HTMLAttributes;
        abbr: React.HTMLAttributes;
        div: React.HTMLAttributes;
        span: React.HTMLAttributes;

        /// so on ...
    }
}
```

### Stateless Functional Components

You can define stateless components simply with the `React.SFC` interface e.g.

```typescript
type Props = {
  foo: string;
}
const MyComponent: React.SFC<Props> = (props) => {
    return <span>{props.foo}</span>
}

<MyComponent foo="bar" />
```

### Stateful Components

Components are type checked based on the `props` property of the component. This is modeled after how JSX is transformed i.e. the attributes become the `props` of the component.

To create React Stateful components you use ES6 classes. The `react.d.ts` file defines the `React.Component<Props,State>` class which you should extend in your own class providing your own `Props` and `State` interfaces. This is demonstrated below:

```typescript
type Props = {
  foo: string;
}
class MyComponent extends React.Component<Props, {}> {
    render() {
        return <span>{this.props.foo}</span>
    }
}

<MyComponent foo="bar" />
```

### React JSX Tip: Interface for renderable

React can render a few things like `JSX` or `string`. These are all consolidated into the type `React.ReactNode` so use it for when you want to accept renderables e.g.

```typescript
type Props = {
  header: React.ReactNode;
  body: React.ReactNode;
}
class MyComponent extends React.Component<Props, {}> {
    render() {
        return <div>
            {this.props.header}
            {this.props.body}
        </div>;
    }
}

<MyComponent foo="bar" />
```

### React JSX Tip: Accept an instance of a Component

The react type definitions provide `React.ReactElement<T>` to allow you to annotate the result of a `<T/>` class component instantiation. e.g.

```javascript
class MyAwesomeComponent extends React.Component {
  render() {
    return <div>Hello</div>;
  }
}

const foo: React.ReactElement<MyAwesomeComponent> = <MyAwesomeComponent />; // Okay
const bar: React.ReactElement<MyAwesomeComponent> = <NotMyAwesomeComponent />; // Error!
```

> Of course you can use this as a function argument annotation and even React component prop member.

### React JSX Tip: Accept a *component* that can act on props and be rendered using JSX

The type `React.Component<Props>` consolidates `React.ComponentClass<P> | React.StatelessComponent<P>` so you can accept *something* that takes type `Props` and renders it using JSX e.g.

```typescript
const X: React.Component<Props> = foo; // from somewhere

// Render X with some props:
<X {...props}/>;
```

### React JSX Tip: Generic components

It works exactly as expected. Here is an example:

```typescript
/** A generic component */
type SelectProps<T> = { items: T[] }
class Select<T> extends React.Component<SelectProps<T>, any> { }

/** Usage */
const Form = () => <Select<string> items={['a','b']} />;
```

### Generic functions

Something like the following works fine:

```typescript
function foo<T>(x: T): T { return x; }
```

However, using an arrow generic function will not:

```typescript
const foo = <T>(x: T) => x; // ERROR : unclosed `T` tag
```

**Workaround**: Use `extends` on the generic parameter to hint the compiler that it's a generic, e.g.:

```typescript
const foo = <T extends {}>(x: T) => x;
```

### React Tip: Strongly Typed Refs

You basically initialize a variable as a union of the ref and `null` and then initiazlie it as as callback e.g.

```typescript
class Example extends React.Component {
  example() {
    // ... something
  }

  render() { return <div>Foo</div> }
}


class Use {
  exampleRef: Example | null = null; 

  render() {
    return <Example ref={exampleRef => this.exampleRef = exampleRef } />
  }
}
```

And the same with ref's for native elements e.g.

```typescript
class FocusingInput extends React.Component<{ value: string, onChange: (value: string) => any }, {}>{
  input: HTMLInputElement | null = null;

  render() {
    return (
      <input
        ref={(input) => this.input = input}
        value={this.props.value}
        onChange={(e) => { this.props.onChange(this.ctrls.input.value) } }
        />
      );
    }
    focus() {
      if (this.input != null) { this.input.focus() }
    }
}
```

### Type Assertions

Use `as Foo` syntax for type assertions as we [mentioned before](https://github.com/overlineink/typescript-book/tree/a8494d4240f834ad9b4965d13504c87f2b1798af/docs/jsx/type-assertion.md#as-foo-vs-foo).

## Default Props

* Stateful components with default props: You can tell TypeScript that a property will be provided externally (by React) by using a *null assertion* operator (this isn't ideal but is the simplest minimum *extra code* solution I could think of).

```
class Hello extends React.Component<{
  /**
   * @default 'TypeScript'
   */
  compiler?: string,
  framework: string
}> {
  static defaultProps = {
    compiler: 'TypeScript'
  }
  render() {
    const compiler = this.props.compiler!;
    return (
      <div>
        <div>{compiler}</div>
        <div>{this.props.framework}</div>
      </div>
    );
  }
}

ReactDOM.render(
  <Hello framework="React" />, // TypeScript React
  document.getElementById("root")
);
```

* SFC with default props: Recommend leveraging simple JavaScript patterns as they work well with TypeScript's type system e.g.

```
const Hello: React.SFC<{
  /**
   * @default 'TypeScript'
   */
  compiler?: string,
  framework: string
}> = ({
  compiler = 'TypeScript', // Default prop
  framework
}) => {
    return (
      <div>
        <div>{compiler}</div>
        <div>{framework}</div>
      </div>
    );
  };


ReactDOM.render(
  <Hello framework="React" />, // TypeScript React
  document.getElementById("root")
);
```
