introduction
Using TypeScript in React projects can significantly improve the maintainability and readability of your code, and provide powerful type checking capabilities to reduce runtime errors. Here are some best practices and tips for elegantly integrating TypeScript into your React project.
1. Create a React TypeScript project
You can use the Create React App to create a TypeScript project:
npx create-react-app my-app --template typescript
2. Configure TypeScript
Make sure yoursThe file is configured correctly. Here is a common one
Configuration:
{ "compilerOptions": { "target": "es5", "lib": ["dom", "", "esnext"], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, "allowSyntheticDefaultImports": true, "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, "jsx": "react-jsx" }, "include": ["src"] }
3. Basic type annotation
Use TypeScript to define the props and state of the component. Here is a simple example:
Function Components
import React from 'react'; interface GreetingProps { name: string; } const Greeting: <GreetingProps> = ({ name }) => { return <h1>Hello, {name}!</h1>; }; export default Greeting;
Class Components
import React, { Component } from 'react'; interface GreetingProps { name: string; } interface GreetingState { count: number; } class Greeting extends Component<GreetingProps, GreetingState> { constructor(props: GreetingProps) { super(props); = { count: 0, }; } render() { return ( <div> <h1>Hello, {}!</h1> <p>Count: {}</p> </div> ); } } export default Greeting;
4. Use Hooks
Use TypeScript to type Hooks:
useState
import React, { useState } from 'react'; const Counter: = () => { const [count, setCount] = useState<number>(0); return ( <div> <p>{count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }; export default Counter;
useReducer
import React, { useReducer } from 'react'; interface State { count: number; } type Action = { type: 'increment' } | { type: 'decrement' }; const initialState: State = { count: 0 }; const reducer = (state: State, action: Action): State => { switch () { case 'increment': return { count: + 1 }; case 'decrement': return { count: - 1 }; default: return state; } }; const Counter: = () => { const [state, dispatch] = useReducer(reducer, initialState); return ( <div> <p>{}</p> <button onClick={() => dispatch({ type: 'increment' })}>Increment</button> <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button> </div> ); }; export default Counter;
5. Context API
Use TypeScript to type Context:
import React, { createContext, useContext, useState, ReactNode } from 'react'; interface AuthContextType { user: string | null; login: (username: string) => void; logout: () => void; } const AuthContext = createContext<AuthContextType | undefined>(undefined); export const AuthProvider: <{ children: ReactNode }> = ({ children }) => { const [user, setUser] = useState<string | null>(null); const login = (username: string) => { setUser(username); }; const logout = () => { setUser(null); }; return ( < value={{ user, login, logout }}> {children} </> ); }; export const useAuth = (): AuthContextType => { const context = useContext(AuthContext); if (!context) { throw new Error('useAuth must be used within an AuthProvider'); } return context; };
6. Advanced Components (HOCs)
When defining advanced components, you need to handle the passed props and enhanced props correctly.
import React, { ComponentType } from 'react'; interface WithLoadingProps { loading: boolean; } const withLoading = <P extends object>( WrappedComponent: ComponentType<P> ): <P & WithLoadingProps> => ({ loading, ...props }) => { if (loading) { return <div>Loading...</div>; } return <WrappedComponent {...(props as P)} />; }; export default withLoading;
7. Type declaration file
If the library you are using does not have a type definition file, you can create a type declaration file. For example, it can besrc/types
Add one to the folderdocument:
// src/types/ declare module 'my-library' { export function myFunction(): string; }
8. Types of using third-party libraries
Install and use the type definition of third-party libraries. For example,lodash
Library
yarn add lodash yarn add @types/lodash --dev # or npm install lodash npm install @types/lodash --save-dev
Then use in the code:
import _ from 'lodash'; const result = _.chunk(['a', 'b', 'c', 'd'], 2);
9. Configure ESLint and Prettier
Use ESLint and Prettier for code quality and style checks:
Install ESLint and Prettier
yarn add eslint eslint-plugin-react @typescript-eslint/parser @typescript-eslint/eslint-plugin --dev yarn add prettier eslint-config-prettier eslint-plugin-prettier --dev # or npm install eslint eslint-plugin-react @typescript-eslint/parser @typescript-eslint/eslint-plugin --save-dev npm install prettier eslint-config-prettier eslint-plugin-prettier --save-dev
Configure ESLint
Create in the project root directory.
document:
= { parser: '@typescript-eslint/parser', extends: [ 'plugin:react/recommended', 'plugin:@typescript-eslint/recommended', 'prettier', 'prettier/@typescript-eslint', 'prettier/react' ], plugins: ['@typescript-eslint', 'react', 'prettier'], parserOptions: { ecmaVersion: 2020, sourceType: 'module', ecmaFeatures: { jsx: true, }, }, settings: { react: { version: 'detect', }, }, rules: { 'prettier/prettier': 'error', }, };
Configure Prettier
Create in the project root directory.prettierrc
document:
{ "singleQuote": true, "trailingComma": "all", "printWidth": 80 }
Summarize
By using TypeScript and combined with React's functions, the robustness and maintainability of the code can be greatly improved. The above practices include basic type annotations, using Hooks, Context API, advanced components, etc. Good tools and configurations such as ESLint and Prettier can also ensure consistent code style and help identify potential problems. Through these measures, TypeScript can be used gracefully in React projects, improving development efficiency and code quality.
Follow-up question: What are the common TS methods used in React?
When using TypeScript in React, there are many common patterns and tricks that can help you manage types and components more efficiently. Here are some common methods and best practices for using TypeScript in React:
1. Basic type annotation
Function Components
Define interfaces for props of function components and useTo define function components:
import React from 'react'; interface GreetingProps { name: string; } const Greeting: <GreetingProps> = ({ name }) => { return <h1>Hello, {name}!</h1>; }; export default Greeting;
Class Components
Define interfaces for props and state of class components and use them in class components:
import React, { Component } from 'react'; interface GreetingProps { name: string; } interface GreetingState { count: number; } class Greeting extends Component<GreetingProps, GreetingState> { constructor(props: GreetingProps) { super(props); = { count: 0, }; } render() { return ( <div> <h1>Hello, {}!</h1> <p>Count: {}</p> <button onClick={() => ({ count: + 1 })}> Increment </button> </div> ); } } export default Greeting;
2. Use Hooks
useState
Define the initial value and type for useState:
import React, { useState } from 'react'; const Counter: = () => { const [count, setCount] = useState<number>(0); return ( <div> <p>{count}</p> <button onClick={() => setCount(count + 1)}>Increment</button> </div> ); }; export default Counter;
useEffect
Define types and dependencies for useEffect:
import React, { useEffect, useState } from 'react'; const Timer: = () => { const [time, setTime] = useState<Date>(new Date()); useEffect(() => { const timer = setInterval(() => { setTime(new Date()); }, 1000); return () => clearInterval(timer); }, []); return <div>{()}</div>; }; export default Timer;
useReducer
Define state and action types for useReducer:
import React, { useReducer } from 'react'; interface State { count: number; } type Action = { type: 'increment' } | { type: 'decrement' }; const initialState: State = { count: 0 }; const reducer = (state: State, action: Action): State => { switch () { case 'increment': return { count: + 1 }; case 'decrement': return { count: - 1 }; default: return state; } }; const Counter: = () => { const [state, dispatch] = useReducer(reducer, initialState); return ( <div> <p>{}</p> <button onClick={() => dispatch({ type: 'increment' })}>Increment</button> <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button> </div> ); }; export default Counter;
3. Use the Context API
Define the type and default values for the Context:
import React, { createContext, useContext, useState, ReactNode } from 'react'; interface AuthContextType { user: string | null; login: (username: string) => void; logout: () => void; } const AuthContext = createContext<AuthContextType | undefined>(undefined); export const AuthProvider: <{ children: ReactNode }> = ({ children }) => { const [user, setUser] = useState<string | null>(null); const login = (username: string) => { setUser(username); }; const logout = () => { setUser(null); }; return ( < value={{ user, login, logout }}> {children} </> ); }; export const useAuth = (): AuthContextType => { const context = useContext(AuthContext); if (!context) { throw new Error('useAuth must be used within an AuthProvider'); } return context; };
4. Use Advanced Components (HOCs)
Define props and types of advanced components:
import React, { ComponentType } from 'react'; interface WithLoadingProps { loading: boolean; } const withLoading = <P extends object>( WrappedComponent: ComponentType<P> ): <P & WithLoadingProps> => ({ loading, ...props }) => { if (loading) { return <div>Loading...</div>; } return <WrappedComponent {...(props as P)} />; }; export default withLoading;
5. Use refs
Define the type for refs:
import React, { useRef, useEffect } from 'react'; const FocusInput: = () => { const inputRef = useRef<HTMLInputElement>(null); useEffect(() => { if () { (); } }, []); return <input ref={inputRef} type="text" />; }; export default FocusInput;
6. Define complex objects and enumerations
Define complex object types and use enumerations:
interface User { id: number; name: string; email: string; } enum UserRole { Admin = 'admin', User = 'user', Guest = 'guest', } const UserProfile: <{ user: User; role: UserRole }> = ({ user, role }) => { return ( <div> <h1>{}</h1> <p>Email: {}</p> <p>Role: {role}</p> </div> ); }; export default UserProfile;
7. Type inference and union type
Type inference and union types using TypeScript:
type Status = 'loading' | 'success' | 'error'; interface LoadingState { status: 'loading'; } interface SuccessState { status: 'success'; data: string; } interface ErrorState { status: 'error'; error: string; } type State = LoadingState | SuccessState | ErrorState; const FetchData: = () => { const [state, setState] = useState<State>({ status: 'loading' }); useEffect(() => { // Simulate data request setTimeout(() => { setState({ status: 'success', data: 'Hello World' }); }, 1000); }, []); if ( === 'loading') { return <div>Loading...</div>; } if ( === 'error') { return <div>Error: {}</div>; } return <div>Data: {}</div>; }; export default FetchData;
Summarize
By using these common TypeScript methods, types and components in a React application can be managed more gracefully. By correctly using TypeScript's type annotation, type inference, and advanced type features, the maintainability, readability and security of your code can be significantly improved. Here are some key points:
- Basic type annotations for function components and class components
- Type definition using Hooks (such as useState, useEffect, useReducer)
- Type definition of Context API
- Type definition of advanced components (HOC)
- Type definition using refs
- The use of complex objects and enumerations
- Type inference and the use of union types
Through these methods, you can take advantage of the power of TypeScript in React to write more robust and reliable code.
The above is the detailed content of the best practices and techniques for React using TypeScript. For more information about React using TypeScript, please follow my other related articles!