React with TypeScript

1. Functional (presentational) component

import React, { MouseEvent } from 'react'interface Props {
onClick(e: MouseEvent<HTMLElement>): void
}
const Button: React.FC<Props> = ({ onClick, children }) => (
<button>
{children}
</button>
)

2. Stateful Component

const initialState = { counter: 0 };
type State = Readonly<typeof initialState>
readonly state: State = initialState
this.state.clicksCount = 55
this.state = { clicksCount: 55 }
import React, { Component, MouseEvent } from 'react';const initialState = { clicksCount: 0 };
type State = Readonly<typeof initialState>;
class ButtonCounter extends Component<object, State> {
readonly state: State = initialState;
render() {
const { clicksCount } = this.state;
return (
<>
<Button onClick={this.handleIncrement}>Add</Button>
<Button onClick={this.handleDecrement}>Decrease</Button>
Counter is: {clicksCount}!
</>
);
}
handleIncrement = () => this.setState(incrementCounter);
handleDecrement = () => this.setState(decrementCounter);
}
const incrementCounter = (prevState: State) => ({ clicksCount: prevState.clicksCount + 1 });const decrementCounter = (prevState: State) => ({ clicksCount: prevState.clicksCount - 1 });
const decrementClicksCount = (prevState: State) 
=> ({ clicksCount: prevState.clicksCount-- })
// Throws complile error:
//
// [ts]
// Cannot assign to 'clicksCount' because it is a constant or a read-only property.

3. Higher order component (enhancers)

interface WithLoadingProps {
loading: boolean;
}
<P extends object>(Component: React.ComponentType<P>)
class WithLoading extends React.Component<P & WithLoadingProps>
return loading ? <LoadingSpinner /> : <Component {...props as P} />;
const withLoading = <P extends object>(Component: React.ComponentType<P>) =>
class WithLoading extends React.Component<P & WithLoadingProps> {
render() {
const { loading, ...props } = this.props;
return loading ? <LoadingSpinner /> : <Component {...props as P} />;
}
};
class WithLoading extends React.Component<P & WithLoadingProps>
const withLoading = <P extends object>(
Component: React.ComponentType<P>
): React.FC<P & WithLoadingProps> => ({
loading,
...props
}: WithLoadingProps) =>
loading ? <LoadingSpinner /> : <Component {...props as P} />;

4. Higher order component (injectors)

export interface InjectedCounterProps {  
value: number;
onIncrement(): void;
onDecrement(): void;
}
<P extends InjectedCounterProps>(Component: React.ComponentType<P>)
class CounterFactory extends React.Component<
Subtract<P, InjectedCounterProps>,
CounterFactoryState
>
const WrappedCounter = counterFactory(Counter);
const wrappedCounter = <WrappedCounter value={2} /> // TS error setting value

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Doing Vue after three years with React

The most popular Open-source GraphQL Servers and Clients

Fullstack Apollo+React GraphQL setup

Which hosting is best for Node JS?

Want To Understand API’s? Read This.

React — Universal Container

React Universal Container

Laravel-Vue.js Datatable Workflow

Previse-HTB-Writeup

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Mindaugas Nakrosis

Mindaugas Nakrosis

More from Medium

Profiling — React Applications

Building a Custom React Hook in TypeScript

Reduce the bundle size of React Application — Lazy load and Preloading of components and routes

Demystifying React’s Context API