Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use it perfectly in React

2025-03-31 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly explains "how to use it perfectly in React". The content in the article is simple and clear, and it is easy to learn and understand. Please follow the editor's train of thought to study and learn "how to use it perfectly in React".

Preface

For a long time, there are many friends around ssh who have a lot of confusion about how to use TS in React. They begin to hate TS and feel that all kinds of inexplicable problems reduce the efficiency of development.

In fact, if you use it skillfully, TS will only spend a little more time writing types at the first development, and it will play a magical role in subsequent maintenance and refactoring, and it is highly recommended for long-term maintenance projects.

In fact, I have always known that there is a good memo in the English version. I originally intended to recommend it directly to my friends, but why many people have a headache about English, and this is the scene in the Chinese translation version:

In that case, do it yourself. Combined with some examples in the original English version to make some extensions, summed up into this memo.

Pre-foundation

The prerequisites for reading this article are:

Familiar with the use of React.

Familiar with type knowledge in TypeScript.

This article will focus on using React Hook as an example, although most of the type knowledge is generic.

In other words, this article focuses on "the combination of React and TypeScript" rather than the basics, which can be learned by reading the documentation.

Tools

TypeScript Playground with React: you can debug React + TypeScript online, you can only debug types, and you cannot run code

Stackblitz: a cloud development tool that runs React code directly and previews

Create React App TypeScript: a project that generates React + TS locally with scaffolding

Just choose the debugging tool you like.

Component Props

Let's take a look at several types that are often used to define Props:

Basic type

Type BasicProps = {message: string; count: number; disabled: boolean; / * * Array Type * / names: string []; / * * limit to the following two "literal string" types with "union type" * / status: "waiting" | "success";}

Object Typ

Type ObjectOrArrayProps = {/ * * if you don't need to use specific attributes, you can vaguely specify that it is an object. ❌ does not recommend * / obj: object; obj2: {}; / / ditto / * * ✅ recommendation for object types with specific attributes * / obj3: {id: string; title: string;}; / * object array? Commonly used * / objArr: {id: string; title: string;} []; / * key can be any string, and the value is limited to MyTypeHere type * / dict1: {[key: string]: MyTypeHere;}; dict2: Record; / / is basically the same as dict1, using the Record type built into TS. }

Function type

Type FunctionProps = {/ * * any function type ❌ is not recommended and cannot specify parameters and return value type * / onSomething: Function; / * * functions without parameters do not need to return values? Commonly used * / onClick: () = > void; / * * with function parameters? It is very common to * / onChange: (id: number) = > void; / * * another function syntax parameter is the button event of React? Very commonly used * / onClick (event: React.MouseEvent): void; / * * optional parameter type? Very commonly used * / optional?: OptionalType;}

React related types

Export declare interface AppProps {children1: JSX.Element; / / ❌ is not recommended without considering the array children2: JSX.Element | JSX.Element []; / / ❌ is not recommended without considering the string children children4: React.ReactChild []; / / slightly better but not considering null children: React.ReactNode; / / ✅ contains all children cases functionChildren: (name: string) = > React.ReactNode / / the function style?: React.CSSProperties; / / ✅ that returns the React node recommends using / / ✅ to recommend all props types that come with native button tags when inlining style / / you can also pass in the generic component to extract the component's Props type props: React.ComponentProps / / ✅ recommends using the previous step to further extract the native onClick function type / / at this time, the first parameter of the function will be automatically inferred to be the click event type onClickButton:React.ComponentProps ["onClick"]} functional component of React.

The simplest:

Interface AppProps = {message: string}; const App = ({message}: AppProps) = > {message}

Containing the children:

Using React.FC built-in types will not only include the AppProps you defined, but also automatically add a children type, as well as types that appear on other components:

/ / equivalent to AppProps & {children: React.ReactNode propTypes?: WeakValidationMap

; contextTypes?: ValidationMap; defaultProps?: Partial

; displayName?: string;} / / use interface AppProps = {message: string}; const App: React.FC = ({message, children}) = > {return ({children} {message})}; Hooks

The @ types/react package begins to support Hooks in versions above 16.8.

UseState

If your default value can already describe the type, then you don't need to declare the type manually, just give it to TS to infer automatically:

/ / val: boolean const [val, toggle] = React.useState (false); toggle (false) toggle (true)

If the initial value is null or undefined, manually pass in the type you want through generics.

Const [user, setUser] = React.useState (null); / / later... SetUser (newUser)

This also ensures that when you directly access the property on user, you will be prompted that it may be null.

This error can be avoided through optional-chaining syntax (supported by TS 3.7or above).

/ / ✅ ok const name = user?.name

UseReducer

You need to use Discriminated Unions to mark the type of Action.

Const initialState = {count: 0}; type ACTIONTYPE = | {type: "increment"; payload: number} | {type: "decrement"; payload: string}; function reducer (state: typeof initialState, action: ACTIONTYPE) {case "increment": return {count: state.count + action.payload}; case "decrement": return {count: state.count-Number (action.payload)}; default: throw new Error () }} function Counter () {const [state, dispatch] = React.useReducer (reducer, initialState); return (Count: {state.count} dispatch ({type: "decrement", payload: "5"})} >-dispatch ({type: "increment", payload: 5})} > +);}

"Discriminated Unions" is generally a union type, in which each type needs to be distinguished by a specific field such as type, and when you pass in a specific type, the remaining types payload will automatically match and infer.

Like this:

When the type you write matches the decrement, TS will automatically infer that the corresponding payload should be of type string.

When the type you write matches increment, then payload should be of type number.

In this way, when you dispatch, enter the corresponding type and automatically prompt you for the remaining parameter types.

UseEffect

The main thing to note here is that the function passed in by useEffect, whose return value is either a method (cleanup function) or undefined, will report an error in other cases.

A common situation is that our useEffect needs to execute an async function, such as:

/ / ❌ / / Type 'Promise' provides no match / / for the signature' (): void | undefined' useEffect (async ()) = > {const user = await getUser () setUser (user)}, [])

Although there is no explicit return value in the async function, the async function returns a Promise by default, which causes TS to report an error.

It is recommended to rewrite it as follows:

UseEffect (() = > {const getUser = async () = > {const user = await getUser () setUser (user)} getUser ()}, [])

Or use self-executing functions? Not recommended, readability is not good.

UseEffect (() = > {(async () = > {const user = await getUser () setUser (user)}) ()}, [])

UseRef

This Hook does not have an initial value in many cases, so you can declare the type of the current property in the returned object:

Const ref2 = useRef (null)

Take a button scenario as an example:

Function TextInputWithFocusButton () {const inputEl = React.useRef (null); const onButtonClick = () = > {if (inputEl & & inputEl.current) {inputEl.current.focus ();}; return (Focus the input);}

When the onButtonClick event is triggered, you can be sure that inputEl also has a value, because the component is rendered at the same level, but you still have to make redundant non-null judgments.

There's a way around it.

Const ref1 = useRef (null!)

Null! This syntax is a non-empty assertion, followed by a value to indicate that you are sure it is valuable, so when you use inputEl.current.focus (), TS will not give an error.

But this syntax is dangerous and needs to be used as little as possible.

In most cases, inputEl.current?.focus () is a safer option, unless the value really cannot be empty. (for example, it is assigned before use)

UseImperativeHandle

It is recommended to use a custom innerRef instead of the native ref, otherwise the type of forwardRef will be very complicated.

Type ListProps = {innerRef?: React.Ref} function List (props: ListProps) {useImperativeHandle (props.innerRef, () = > ({scrollToTop () {}})) return null}

Combined with the knowledge just learned from useRef, the usage goes like this:

Function Use () {const listRef = useRef (null!) UseEffect (() = > {listRef.current.scrollToTop ()}, []) return ()}

It's perfect, isn't it?

Custom Hook

If you want to return an array to the user in the form of useState, be sure to use as const when appropriate, mark the return value as a constant, tell TS that the values in the array will not be deleted, change the order, and so on.

Otherwise, each of your items will be inferred as a "joint type of all types of possibilities", which will affect user use.

Export function useLoading () {const [isLoading, setState] = React.useState (false); const load = (aPromise: Promise) = > {setState (true); return aPromise.finally (() = > setState (false));}; / / ✅ adds as const to infer that [boolean, typeof load] / / ❌ would otherwise be (boolean | typeof load) [] return [isLoading, load] as const; []}

By the way, if you are writing a library in React Hook, don't forget to export the type to the user as well.

React API

ForwardRef

Functional components cannot add ref by default, and they do not have their own instances like class components. This API is generally used by functional components to receive ref from the parent component.

So you need to label the instance type, that is, what type of value the parent component can get through ref.

Type Props = {}; export type Ref = HTMLButtonElement; export const FancyButton = React.forwardRef ((props, ref) = > ({props.children}))

Since ref is forwarded directly to button in this example, you can simply mark the type as HTMLButtonElement.

When the parent component is called like this, you can get the correct type:

Export const App = () = > {const ref = useRef () return ()} Thank you for your reading. The above is the content of "how to use it perfectly in React". After the study of this article, I believe you have a deeper understanding of how to use it perfectly in React, and the specific use needs to be verified in practice. Here is, the editor will push for you more related knowledge points of the article, welcome to follow!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report