Summary of the use of TypeScript in React projects

Summary of the use of TypeScript in React projects

Preface

This article will focus on the use of TypeScript (hereinafter referred to as TS) in conjunction with React in projects, rather than the basic concepts of TS. For TS type checking, you can use online TS tools 👉TypeScript Playground

React element related

React element-related types mainly include ReactNode , ReactElement , and JSX.Element .

  • ReactNode . Represents any type of React node. This is a union type that covers many situations.
  • ReactElement/JSX . From the performance point of view, the two can be considered to be consistent, belonging to the subset of ReactNode , representing "native DOM components" or "execution results of custom components".

The following are some usage examples:

const MyComp: React.FC<{ title: string; }> = ({title}) => <h2>{title}</h2>;

// ReactNode
const a: React.ReactNode =
  null ||
  undefined || <div>hello</div> || <MyComp title="world" /> ||
  "abc" ||
  123 ||
  true;

// ReactElement and JSX.Element
const b: React.ReactElement = <div>hello world</div> || <MyComp title="good" />;

const c: JSX.Element = <MyComp title="good" /> || <div>hello world</div>;

Native DOM related

The native DOM-related types mainly include the following: Element , HTMLElement , HTMLxxxElment .

In simple terms: Element = HTMLElement + SVGElement .

SVGElement is rarely used in general development, but HTMLElement is very common. Its subtypes include HTMLDivElement , HTMLInputElement , HTMLSpanElement , and so on.

Therefore, we can know that the relationship is: Element > HTMLElement > HTMLxxxElement . In principle, it is better to write as detailed as possible.

React Synthetic Events

In React, native events are processed into React events, which internally optimize memory and reduce DOM event binding through event delegation. Back to the point, the general format of React events is [xxx]Event, common ones are MouseEvent , ChangeEvent , TouchEvent , which is a generic type, and the generic variable is the type of DOM element that triggers the event.

Here is an example:

// Input text into the input box const handleInputChange = (evt: React.ChangeEvent<HTMLInputElement>) => {
  console.log(evt);
};

// button click const handleButtonClick = (evt: React.MouseEvent<HTMLButtonElement>) => {
  console.log(evt);
};

// Mobile terminal touch div
const handleDivTouch = (evt: React.TouchEvent<HTMLDivElement>) => {
  console.log(evt);
};

Combination with hooks

Among hooks, not all hooks are strongly associated with TS. For example, useEffect does not rely on TS for type definition. Let's take a look at several common hooks that are strongly associated with TS.

useState

If the initial value can describe the type, there is no need to specify a generic variable for useState;

// ❌This is unnecessary because the initial value 0 already describes the count type const [count, setCount] = useState<number>(0);

// ✅This is better const [count, setCount] = useState(0);

If the initial value is null or undefined, you need to manually pass in the expected type through generics and avoid syntax errors through optional chaining when accessing properties.

interface IUser {
  name: string;
  age: number;
}

const [user, setUser] = React.useState<IUser | null>(null);

console.log(user?.name);

useRef

This hook is quite special, it usually has two uses:

Used to connect to DOM to obtain DOM elements;

// Connect to DOM, the initial value is null, not undefined. If you want to specify a generic variable, you need to specify HTMLxxxElement
// If we are sure that inputRef.current must have a value when calling, we can use a non-null assertion and add it after null!
const inputRef = useRef<HTMLInputElement>(null!);

const handleClick = () => {
  inputRef.current.focus(); // Of course, you don't need a non-null assertion, you can also use inputEl.current?.focus() optional chaining}

return (
  <input ref={inputRef} />
  <button onClick={handleClick}>Click</button>
)

2. Used to store variables. Since it is stored outside the functional component, compared to useState, it will not have the problem of asynchronous updates, nor will it have the problem of outdated variables caused by capture-value feature. However, it should be noted that after assignment, since the ref reference has not changed, it will not cause re-rendering.

// Automatically specify the generic variable type through the initial value const sum = useRef(0);

// Directly assign sum.current = 3 through .current;
// There is no asynchronous update problem console.log(sum.current); // 3

useSelector

useSelector is used to obtain the state in the store. Its first fixed parameter is a function, and the input parameter of the function is the store. The type of the store, RootState, needs to be defined in the store in advance. A common definition is as follows:

In store.ts:

const store = createStore(rootReducer);

export type RootState = ReturnType<typeof rootReducer>;

When using:

const { var1, var2 } = useSelector((store: RootState) => store.xxx);

Custom hooks

If we need to return an array in the same way as useState, we need to use as const at the end of the return value to mark it as a constant, otherwise the returned value will be inferred to be a union type.

const useInfo = () => {
  const [age, setAge] = useState(0);

  return [age, setAge] as const; // The type is a tuple, [number, React.Dispatch<React.SetStateAction<number>>]
};

redux related

For the definition of action, we can use the officially exposed AnyAction and relax the restrictions on the key-value pairs inside the action, as follows:

import { AnyAction } from "redux";

const DEF_STATE = {
  count: 0,
  type: 'integer'
};

// Use redux's AnyAction to relax restrictions function countReducer(state = DEF_STATE, action: AnyAction) {
  switch (action.type) {
    case "INCREASE_COUNT":
      return {
        ...state,
        count: state.count + 1,
      };
    case "DECREASE_COUNT":
      return {
        ...state,
        count: state.count - 1,
      };
    default:
      return state;
  }
}

export default countReducer;

Regulations

The input parameters of the subcomponent are named [component name] Props, such as:

// For example, the current component name is InfoCard
export interface InfoCardProps {
  name: string;
  age: number;
}

Interface types start with uppercase;

Write interfaces for the input and output parameters of the backend interface, and use the jsdoc style to make comments that are convenient for editor prompts, such as:

export interface GetUserInfoReqParams {
    /** name*/
    name: string;
    /** age*/
    age: number;
    /** gender*/
    gender: string;
}

other

Not sure what to do with the key name or value?

// Indicates that the key name is uncertain and the key value is limited to number type export interface NotSureAboutKey {
  [key: string]: number;
}

// When the key name and value are uncertain, the following interface is applicable to any object export interface AllNotSure {
  [key: string]: any;
}

How to use generic variables in interfaces?

The so-called generics are predefined types. Its purpose is to achieve local flexibility in type definition and improve reusability. We usually use generics in interfaces, such as:

// Usually, we specify a default type for the generic variable of the interface interface IHuman<T = unknown> {
  name: string;
  age: number;
  gender: T;
}

// When used elsewhere const youngMan: IHuman<string> = {
    name: 'zhangsan',
    age: 18,
    gender: 'male'
}

This concludes this article on the use of TypeScript in React projects. For more information about the use of TypeScript in React, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Implementation of TypeScript in React project
  • React+ts realizes secondary linkage effect
  • TypeScript generic parameter default types and new strict compilation option
  • Step by step guide to build a calendar component with React
  • Practical tips for TS type filtering in front-end React Nextjs

<<:  Detailed explanation of the principle of distributed locks and three implementation methods

>>:  Linux beginners in virtual machines configure IP and restart the network

Recommend

Summary of MySQL data migration

Table of contents Preface: 1. About data migratio...

Tutorial on installing DAMO database on Centos7

1. Preparation After installing the Linux operati...

A brief discussion on MySQL select optimization solution

Table of contents Examples from real life Slow qu...

How to use vue3 to build a material library

Table of contents Why do we need a material libra...

Detailed explanation of the use of filter properties in CSS3

Recently, when I was modifying the intranet porta...

Common parameters of IE web page pop-up windows can be set by yourself

The pop-up has nothing to do with whether your cur...

mysql5.7 create user authorization delete user revoke authorization

1. Create a user: Order: CREATE USER 'usernam...

A complete example of implementing a timed crawler with Nodejs

Table of contents Cause of the incident Use Node ...

How to use the Linux nl command

1. Command Introduction nl (Number of Lines) adds...

MySQL Series 14 MySQL High Availability Implementation

1. MHA ​By monitoring the master node, automatic ...

Detailed installation and use of RocketMQ in Docker

To search for RocketMQ images, you can search on ...

Example of implementing translation effect (transfrom: translate) with CSS3

We use the translate parameter to achieve movemen...

Detailed explanation of how to mount remote file systems via SSH on Linux

Features of SSHFS: Based on FUSE (the best usersp...

MySQL high availability solution MMM (MySQL multi-master replication manager)

1. Introduction to MMM: MMM stands for Multi-Mast...

CSS code to control the background color of the web page

I think everyone often worries about finding pict...