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

css Get all elements starting from the nth one

The specific code is as follows: <div id="...

Introduction to basic concepts and technologies used in Web development

Today, this article introduces some basic concept...

How to use Linux paste command

01. Command Overview The paste command will merge...

MySQL 5.7.15 version installation and configuration method graphic tutorial

This article shares with you a detailed tutorial ...

How to move a red rectangle with the mouse in Linux character terminal

Everything is a file! UNIX has already said it. E...

Detailed explanation of cross-usage of Ref in React

Table of contents 1. First, let’s explain what Re...

An example of vertical centering of sub-elements in div using Flex layout

1. Flex is the abbreviation of Flexible Box, whic...

How to define data examples in Vue

Preface In the development process, defining vari...

Detailed analysis of the usage and application scenarios of slots in Vue

What are slots? We know that in Vue, nothing can ...

Bootstrap realizes the effect of carousel

This article shares the specific code of Bootstra...

Detailed explanation of Vue filters

<body> <div id="root"> <...

jQuery achieves the effect of advertisement scrolling up and down

This article shares the specific code of jQuery t...

Introduction to container data volumes in Docker

Table of contents Docker container data volume Us...