Udforsk bedste praksis for at bruge TypeScript med React til at bygge robuste, skalerbare og vedligeholdelsesvenlige webapplikationer. Lær om projektstruktur, komponentdesign, test og optimering.
TypeScript med React: Bedste praksis for skalerbare og vedligeholdelsesvenlige applikationer
TypeScript og React er en stærk kombination til at bygge moderne webapplikationer. TypeScript bringer statisk typning til JavaScript, hvilket forbedrer kodekvaliteten og vedligeholdelsesvenligheden, mens React giver en deklarativ og komponentbaseret tilgang til at bygge brugergrænseflader. Dette blogindlæg udforsker bedste praksis for at bruge TypeScript med React til at skabe robuste, skalerbare og vedligeholdelsesvenlige applikationer, der er egnede til et globalt publikum.
Hvorfor bruge TypeScript med React?
Før vi dykker ned i den bedste praksis, lad os forstå, hvorfor TypeScript er en værdifuld tilføjelse til React-udvikling:
- Forbedret kodekvalitet: TypeScript's statiske typning hjælper med at fange fejl tidligt i udviklingsprocessen, hvilket reducerer runtime-problemer og forbedrer kode pålideligheden.
- Forbedret vedligeholdelsesvenlighed: Type annotationer og grænseflader gør koden lettere at forstå og refactorere, hvilket fører til bedre langsigtet vedligeholdelsesvenlighed.
- Bedre IDE-support: TypeScript giver fremragende IDE-support, herunder automatisk fuldførelse, kodenavigation og refactoring-værktøjer, hvilket øger udviklerproduktiviteten.
- Reduceret antal fejl: Statisk typning fanger mange almindelige JavaScript-fejl før runtime, hvilket fører til en mere stabil og fejlfri applikation.
- Forbedret samarbejde: Tydelige typedefinitioner gør det lettere for teams at samarbejde om store projekter, da udviklere hurtigt kan forstå formålet og brugen af forskellige komponenter og funktioner.
Opsætning af et TypeScript React-projekt
Brug af Create React App
Den nemmeste måde at starte et nyt TypeScript React-projekt er ved at bruge Create React App med TypeScript-skabelonen:
npx create-react-app my-typescript-react-app --template typescript
Denne kommando opsætter et grundlæggende React-projekt med TypeScript konfigureret, herunder nødvendige afhængigheder og en tsconfig.json
-fil.
Konfiguration af tsconfig.json
tsconfig.json
-filen er hjertet i din TypeScript-konfiguration. Her er nogle anbefalede indstillinger:
{
"compilerOptions": {
"target": "es5",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx"
},
"include": [
"src"
]
}
Vigtige muligheder at overveje:
"strict": true
: Aktiverer streng typekontrol, hvilket anbefales stærkt til at fange potentielle fejl."esModuleInterop": true
: Aktiverer interoperabilitet mellem CommonJS og ES-moduler."jsx": "react-jsx"
: Aktiverer den nye JSX-transformation, som forenkler React-kode og forbedrer ydeevnen.
Bedste praksis for React-komponenter med TypeScript
Typning af komponent-props
Et af de vigtigste aspekter ved at bruge TypeScript med React er korrekt typning af dine komponent-props. Brug grænseflader eller typealiasser til at definere formen af props-objektet.
interface MyComponentProps {
name: string;
age?: number; // Valgfri prop
onClick: () => void;
}
const MyComponent: React.FC = ({ name, age, onClick }) => {
return (
Hello, {name}!
{age && You are {age} years old.
}
);
};
Brug af React.FC<MyComponentProps>
sikrer, at komponenten er en funktionel komponent, og at propsene er korrekt typet.
Typning af komponenttilstand
Hvis du bruger klassekomponenter, skal du også type komponents tilstand. Definer en grænseflade eller typealias for tilstandsobjektet, og brug det i komponentdefinitionen.
interface MyComponentState {
count: number;
}
class MyComponent extends React.Component<{}, MyComponentState> {
state: MyComponentState = {
count: 0
};
handleClick = () => {
this.setState({
count: this.state.count + 1
});
};
render() {
return (
Count: {this.state.count}
);
}
}
For funktionelle komponenter, der bruger useState
-hooket, kan TypeScript ofte udlede typen af tilstandsvariablen, men du kan også eksplicit angive den:
import React, { useState } from 'react';
const MyComponent: React.FC = () => {
const [count, setCount] = useState(0);
return (
Count: {count}
);
};
Brug af type guards
Type guards er funktioner, der indsnævrer typen af en variabel inden for et specifikt omfang. De er nyttige, når du har at gøre med unionstyper, eller når du skal sikre, at en variabel har en bestemt type, før du udfører en operation.
interface Circle {
kind: "circle";
radius: number;
}
interface Square {
kind: "square";
side: number;
}
type Shape = Circle | Square;
function isCircle(shape: Shape): shape is Circle {
return shape.kind === "circle";
}
function getArea(shape: Shape): number {
if (isCircle(shape)) {
return Math.PI * shape.radius ** 2;
} else {
return shape.side ** 2;
}
}
isCircle
-funktionen er en type guard, der kontrollerer, om en Shape
er en Circle
. Inden for if
-blokken ved TypeScript, at shape
er en Circle
og giver dig mulighed for at få adgang til dens radius
-egenskab.
Håndtering af begivenheder
Når du håndterer begivenheder i React med TypeScript, er det vigtigt at type eventobjektet korrekt. Brug den relevante eventtype fra React
-navneområdet.
const MyComponent: React.FC = () => {
const handleChange = (event: React.ChangeEvent) => {
console.log(event.target.value);
};
return (
);
};
I dette eksempel bruges React.ChangeEvent<HTMLInputElement>
til at type eventobjektet for en ændringsbegivenhed på et inputelement. Dette giver adgang til target
-egenskaben, som er et HTMLInputElement
.
Projektstruktur
En velstruktureret projekt er afgørende for vedligeholdelsesvenlighed og skalerbarhed. Her er en foreslået projektstruktur for en TypeScript React-applikation:
src/
├── components/
│ ├── MyComponent/
│ │ ├── MyComponent.tsx
│ │ ├── MyComponent.module.css
│ │ └── index.ts
├── pages/
│ ├── HomePage.tsx
│ └── AboutPage.tsx
├── services/
│ ├── api.ts
│ └── auth.ts
├── types/
│ ├── index.ts
│ └── models.ts
├── utils/
│ ├── helpers.ts
│ └── constants.ts
├── App.tsx
├── index.tsx
├── react-app-env.d.ts
└── tsconfig.json
Vigtige punkter:
- Komponenter: Gruppér relaterede komponenter i mapper. Hver mappe skal indeholde komponentens TypeScript-fil, CSS-moduler (hvis de bruges) og en
index.ts
-fil til eksport af komponenten. - Sider: Gem topniveaukomponenter, der repræsenterer forskellige sider i din applikation.
- Tjenester: Implementer API-kald og andre tjenester i denne mappe.
- Typer: Definer globale typedefinitioner og grænseflader i denne mappe.
- Utils: Gem hjælpefunktioner og konstanter.
- index.ts: Brug
index.ts
-filer til at eksportere moduler fra en mappe igen, hvilket giver en ren og organiseret API til import af moduler.
Brug af hooks med TypeScript
React Hooks giver dig mulighed for at bruge tilstand og andre React-funktioner i funktionelle komponenter. TypeScript fungerer problemfrit med Hooks, hvilket giver typesikkerhed og forbedret udvikleroplevelse.
useState
Som vist tidligere kan du eksplicit type tilstandsvariablen, når du bruger useState
:
import React, { useState } from 'react';
const MyComponent: React.FC = () => {
const [count, setCount] = useState(0);
return (
Count: {count}
);
};
useEffect
Når du bruger useEffect
, skal du være opmærksom på afhængighedsarrayet. TypeScript kan hjælpe dig med at fange fejl, hvis du glemmer at inkludere en afhængighed, der bruges i effekten.
import React, { useState, useEffect } from 'react';
const MyComponent: React.FC = () => {
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `Count: ${count}`;
}, [count]); // Tilføj 'count' til afhængighedsarrayet
return (
Count: {count}
);
};
Hvis du udelader count
fra afhængighedsarrayet, køres effekten kun én gang, når komponenten monteres, og dokumentets titel opdateres ikke, når antallet ændres. TypeScript advarer dig om dette potentielle problem.
useContext
Når du bruger useContext
, skal du angive en type for kontekstværdien.
import React, { createContext, useContext } from 'react';
interface ThemeContextType {
theme: string;
toggleTheme: () => void;
}
const ThemeContext = createContext(undefined);
const ThemeProvider: React.FC = ({ children }) => {
// Implementer temalogik her
return (
{} }}>
{children}
);
};
const MyComponent: React.FC = () => {
const { theme, toggleTheme } = useContext(ThemeContext) as ThemeContextType;
return (
Theme: {theme}
);
};
export { ThemeProvider, MyComponent };
Ved at angive en type for kontekstværdien sikrer du, at useContext
-hooket returnerer en værdi med den korrekte type.
Test af TypeScript React-komponenter
Test er en væsentlig del af at bygge robuste applikationer. TypeScript forbedrer test ved at give typesikkerhed og forbedret kodedækning.
Enhedstest
Brug testrammer som Jest og React Testing Library til at enhedsteste dine komponenter.
// MyComponent.test.tsx
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import MyComponent from './MyComponent';
descrive('MyComponent', () => {
it('renders the component with the correct name', () => {
render( );
expect(screen.getByText('Hello, John!')).toBeInTheDocument();
});
it('calls the onClick handler when the button is clicked', () => {
const onClick = jest.fn();
render( );
fireEvent.click(screen.getByRole('button'));
expect(onClick).toHaveBeenCalledTimes(1);
});
});
TypeScript's typekontrol hjælper med at fange fejl i dine tests, såsom at sende forkerte props eller bruge de forkerte eventhandlere.
Integrationstest
Integrationstests verificerer, at forskellige dele af din applikation fungerer korrekt sammen. Brug værktøjer som Cypress eller Playwright til end-to-end-test.
Ydeevneoptimering
TypeScript kan også hjælpe med ydeevneoptimering ved at fange potentielle ydeevneflaskehalse tidligt i udviklingsprocessen.
Memoisering
Brug React.memo
til at memoisere funktionelle komponenter og forhindre unødvendige gen-renderinger.
import React from 'react';
interface MyComponentProps {
name: string;
}
const MyComponent: React.FC = ({ name }) => {
console.log('Rendering MyComponent');
return (
Hello, {name}!
);
};
export default React.memo(MyComponent);
React.memo
vil kun gen-rendere komponenten, hvis propsene er blevet ændret. Dette kan forbedre ydeevnen betydeligt, især for komplekse komponenter.
Kodesplitning
Brug dynamiske imports til at opdele din kode i mindre bidder og indlæse dem efter behov. Dette kan reducere den indledende indlæsningstid for din applikation.
import React, { Suspense } from 'react';
const MyComponent = React.lazy(() => import('./MyComponent'));
const App: React.FC = () => {
return (
Loading...
React.lazy
giver dig mulighed for dynamisk at importere komponenter, som kun indlæses, når de er nødvendige. Suspense
-komponenten giver en fallback-UI, mens komponenten indlæses.
Konklusion
Brug af TypeScript med React kan forbedre kvaliteten, vedligeholdelsesvenligheden og skalerbarheden af dine webapplikationer betydeligt. Ved at følge disse bedste praksis kan du udnytte kraften i TypeScript til at bygge robuste og performante applikationer, der opfylder behovene hos et globalt publikum. Husk at fokusere på klare typedefinitioner, velstruktureret projektorganisation og grundig test for at sikre den langsigtede succes for dine projekter.