React class components typescript

reacttypescript How to create React components with TypeScript

Using TypeScript together with React has proven to be a powerful combination.

Some people are afraid to move to TypeScript because they think it forces you to write a lot of boilerplate code. In my experience, once these people give TypeScript a try, they won’t go back to writing Vanilla JavaScript again.

I want to take this fear from you by showing how you can easily define your React components with TypeScript in this article.

Functional components with TypeScript

You can create functional components in TypeScript just like you would in JavaScript.

The main difference is the FC interface, which stands for Function Component. We use this to tell TypeScript that this is a React function component and not just a regular function.

Optionally, we can add types for the props by defining an interface and passing it to the generic FC .

A functional component then typically looks like this:

import React,  FC > from 'react'; interface TitleProps  title: string; > const Title: FCTitleProps> = ( title, subtitle >) =>  return ( > h1>title>h1> h2>subtitle>h2> > ); >; export default Title;

If we now use this component somewhere in our application, we get to reap the benefits of this:

We get autocompletion and compilation errors in our editor that warn us when we forgot a property or use the wrong types.

Compilation error example

Generic types in TypeScript are like functions that accept parameters. Instead of parentheses, generic types use angle brackets ( <> ).

For the FC interface, you don’t need to pass any parameters, so you could use it without a generic type by omitting the angle brackets altogether when your component doesn’t accept any props:

Not all of your props need to be required. We can make a prop optional by adding a question mark to the interface:

interface TitleProps  title: string; // required subtitle?: string; // optional >

This will allow you to omit the prop when you don’t need it.

Alternatives to the FC interface

If you already know TypeScript, you might have wondered why I’m not applying the prop interface to the function parameters itself.

const Title = ( title, subtitle >: TitleProps) =>  // . >

The syntax above works fine as well. In fact, many people write function components like this in TypeScript.

However, the reason why you might want to use a generic type like FC is that this comes with all the typings that you could possibly need for a function component.

This includes, for example, the implicit children property. Being a default prop of any React component, we don’t need to add it to our interface.

import React,  FC > from 'react'; interface TitleProps  title: string; subtitle?: string; > const Title: FCTitleProps> = ( title, subtitle, children >) =>  return ( > h1>title>h1> h2>subtitle>h2> div>children>div> > ); >; export default Title;

This can be seen as a disadvantage though. Imagine you don’t want your component to accept children. The FC interface always adds the children prop, regardless of whether you use it or not.

It would be better to define the props without React’s generic interface and use FC in the case you want to access the children property.

I’ve come across the FC and the FunctionComponent interfaces and wondered what advantages one had over the other.

A quick look at React’s type definitions revealed that FC is just the shorthand for FunctionComponent . Both refer to the same interface.

type FCP = >> = FunctionComponentP>;

Type-safe state in function components

To have type-safety for the state in functional components, we don’t necessarily need to modify our code: The useState hook inherits the type from the value we use to initialize it.

If we use a more complex type or don’t initialize the state, we can pass the type like the following:

const [title, setTitle] = useStatestring>(null);

Replace string with whatever type you need.

Class components in TypeScript

Although I default to writing functional components, some cases require me to work with class components as well.

Let’s jump right into it and have a look at the previous example as a class component in TypeScript.

import React,  Component > from 'react'; interface TitleProps  title: string; subtitle?: string; > class Title extends ComponentTitleProps>  render()  const  title, subtitle, children > = this.props; return ( > h1>title>h1> h2>subtitle>h2> div>children>div> > ); > > export default Title;

As we can see here, we extend React’s Component class just like we would when working with JavaScript.

However, this class interface is generic, so we can pass an interface to it that contains the types of our props Component .

Type-safe state in class components

We can also make our state type-safe by creating an interface for it and passing it as a parameter to Component :

import React,  Component > from 'react'; interface TitleProps  title: string; subtitle?: string; > interface TitleState  counter: number;> class Title extends ComponentTitleProps, TitleState>  // . > export default Title;

We’ll typically use constructors to initialize our class component’s state.

Unfortunately, the React class won’t know the type of our props automatically, which is why we need to specify the type of the props parameter in the function call:

constructor(props: TitleProps)  super(props); this.state =  counter: 0, >; >

If we don’t do this and we run our code in strict mode, TypeScript will throw a compilation error.

We can define the default values of our properties by adding the static variable defaultProps to our class component:

interface TitleProps  title: string; subtitle?: string; > class Title extends ComponentTitleProps, TitleState>   public static defaultProps =  title: 'Hey there!', >; //. >

The React component is smart enough to inherit the prop types.

In the example, title is a required property, however, since we’ve defined a default prop, it automatically becomes optional.

TypeScript won’t throw an error if we don’t add a title prop in this case, even though it’s required in our interface.

As you can see, using TypeScript for your React isn’t too complicated and the amount of code you need to write is limited.

In exchange for this bit of extra effort, you get rewarded with type-safety and autocompletion, which results in a more solid code-base as it helps you to catch bugs early on during development.

If you want to learn more about how to use TypeScript with React, make sure to subscribe to my newsletter, so you don’t miss my future articles.

Источник

TypeScript and React: Components

Stefan Baumgartner

Components are at the heart of React. Let’s see what we can do to get better error handling and tooling for them!

Functional components #

Functional components are my most favourite thing in React. They are simple, purely functional and super easy to reason about. The following shows an example of a functional component with some typed properties.

import React from 'react'; // we need this to make JSX compile

type CardProps =
title: string,
paragraph: string
>

export const Card = ( title, paragraph >: CardProps) => aside>
h2> title >/h2>
p>
paragraph >
/p>
/aside>

const el = Card title="Welcome!" paragraph="To this example" />

We use as little TypeScript as possible. Creating a type for our properties, and telling TypeScript that the parameters of our functional component are of that type. You already get nice suggestions in VS Code:

Autocompletion in VS Code

And errors when you compile without passing all required properties:

Error message in command line

If you want to make some properties optional, do that in the respective Props type:

type CardProps =  
title: string,
paragraph?: string // the paragraph is optional
>

There’s a generic type you can use.

import React,  FunctionComponent > from 'react'; // importing FunctionComponent

type CardProps =
title: string,
paragraph: string
>

export const Card: FunctionComponentCardProps> = ( title, paragraph >) => aside>
h2> title >/h2>
p>
paragraph >
/p>
/aside>

const el = Card title="Welcome!" paragraph="To this example" />

The parameters of our function are infered from the generic FunctionComponent. Other than that, it seems very similar to the first example. However, it allows for optional child components:

type CardProps =  
title: string,
paragraph: string
>

// we can use children even though we haven't defined them in our CardProps
export const Card: FunctionComponentCardProps> = ( title, paragraph, children >) => aside>
h2> title >/h2>
p>
paragraph >
/p>
children >
/aside>

More on the usage of child components in Children.

Class components #

One of the things that convinced me to use React were functional components. The “olde way” of doing components is with class components. And they can keep state per class. State is like props, but private and only controlled by the component.

@types/react typings of course have full support for those, and are also equally easy to use.

Class components need to be extended from the base React.Component class. Typings enhance this class with generics, passing props (like FunctionComponent earlier) and state. Let’s do a clock component:

import React,  Component > from 'react'; // let's also import Component

// the clock's state has one field: The current time, based upon the
// JavaScript class Date
type ClockState =
time: Date
>

// Clock has no properties, but the current state is of type ClockState
// The generic parameters in the Component typing allow to pass props
// and state. Since we don't have props, we pass an empty object.
export class Clock extends Component>, ClockState>

// The tick function sets the current state. TypeScript will let us know
// which ones we are allowed to set.
tick()
this.setState(
time: new Date()
>);
>

// Before the component mounts, we initialise our state
componentWillMount()
this.tick();
>

// After the component did mount, we set the state each second.
componentDidMount()
setInterval(() => this.tick(), 1000);
>

// render will know everything!
render()
return p>The current time is this.state.time.toLocaleTimeString()>/p>
>
>

And through proper tooling, we get a ton of infos:

First, setState is aware of its state properties and only allows to set those. Even if you have more state properties, TypeScript allows you to only set those you want to update.

setState only allows to set time

When we access state in our render function, we have access to all its properties. Here we see time , and it’s of type Date

state has only one element time, it

Date of course is a built-in JavaScript type, so we get full access to all its methods. Ever wanted to know what Date can do? Let TypeScript tell you:

Date is a built-in JS type, we have full autocompletion

That’s a lot of tooling support, just for a couple of keystrokes more. The type inference of React does the rest.

constructors #

The constructor function is a bit special. You need to pass your props there (even if you don’t have any), and TypeScript requires you to pass the to the super constructor function.

However, when writing the typical pattern of constructors and super calls in TypeScript’s strict mode, you will get an error if you don’t provide any typings yourself. This is because you create a new class, with a completly new constructor, and TypeScript does not know which parameters to expect!

Therefore, TypeScript will imply them to be any . And implicit any in strict mode is not allowed.

export class Sample extends ComponentSampleProps>  
constructor(props) // ️⚡️ does not compile in strict mode
super(props)
>
>

Even though the super call knows which props to expect, we need to be explicit with our constructor function:

export class Sample extends ComponentSampleProps>  
constructor(props: SampleProps)
super(props)
>
>

defaultProps #

Default properties allow you to specifcy default values for properties. In case you don’t want to have every value to be set explicitly. React has the property defaultProps reserved for components.

TypeScript in version 3.0 is honouring defaultProps . With the latest React typings (v 16.4.8) you are ready to go:

import React,  Component > from 'react';

type NoticeProps =
msg: string
>

export class Notice extends ComponentNoticeProps>
static defaultProps =
msg: 'Hello everyone!'
>

render()
return p> this.props.msg >/p>
>
>

const el = Notice /> // Will compile in TS 3.0

For FunctionComponents, I suggest using the ES6 default value syntax and optional type properties:

type CardProps =  
title: string,
paragraph?: string // the paragraph is optional
>

// No need to define the defaultProps property
export const Card: FunctionComponentCardProps> = ( title, paragraph = 'Hello World' >) =>
aside>
h2> title >/h2>
p>
paragraph >
/p>
/aside>

Bottom line #

You already can see that you don’t have to write that many typings or boilerplate code in React to get into the nice tooling and type safety features of TypeScript. Components are a huge deal in React, and with just a couple of keystrokes we have everything we need.

Let’s see what else we can do in the next section.

Источник

Читайте также:  Insert html to mysql database
Оцените статью