Tutustu TypeScriptin ja Reactin parhaisiin käytäntöihin vankkojen, skaalautuvien ja ylläpidettävien verkkosovellusten rakentamiseksi. Opi projektirakenteesta, komponenttisuunnittelusta, testauksesta ja optimoinnista.
TypeScript ja React: Parhaat käytännöt skaalautuvien ja ylläpidettävien sovellusten rakentamiseen
TypeScript ja React ovat tehokas yhdistelmä nykyaikaisten verkkosovellusten rakentamiseen. TypeScript tuo staattisen tyypityksen JavaScriptiin, parantaen koodin laatua ja ylläpidettävyyttä, kun taas React tarjoaa deklaratiivisen ja komponenttipohjaisen lähestymistavan käyttöliittymien rakentamiseen. Tässä blogikirjoituksessa tutustutaan parhaisiin käytäntöihin TypeScriptin ja Reactin käyttämiseksi vankkojen, skaalautuvien ja ylläpidettävien sovellusten luomiseen, jotka soveltuvat maailmanlaajuiselle yleisölle.
Miksi käyttää TypeScriptiä Reactin kanssa?
Ennen kuin syvennymme parhaisiin käytäntöihin, katsotaan miksi TypeScript on arvokas lisä React-kehitykseen:
- Parempi koodin laatu: TypeScriptin staattinen tyypitys auttaa havaitsemaan virheitä varhaisessa kehitysvaiheessa, mikä vähentää ajonaikaisia ongelmia ja parantaa koodin luotettavuutta.
- Parempi ylläpidettävyys: Tyyppimäärittelyt ja rajapinnat tekevät koodista helpommin ymmärrettävää ja uudelleenmuokattavaa, mikä johtaa parempaan pitkän aikavälin ylläpidettävyyteen.
- Parempi IDE-tuki: TypeScript tarjoaa erinomaisen IDE-tuen, mukaan lukien automaattisen täydennyksen, koodissa navigoinnin ja refaktorointityökalut, mikä lisää kehittäjien tuottavuutta.
- Vähemmän bugeja: Staattinen tyypitys nappaa monia yleisiä JavaScript-virheitä ennen ajoa, mikä johtaa vakaampaan ja virheettömämpään sovellukseen.
- Parempi yhteistyö: Selkeät tyyppimäärittelyt helpottavat tiimien yhteistyötä suurissa projekteissa, sillä kehittäjät voivat nopeasti ymmärtää eri komponenttien ja funktioiden tarkoituksen ja käytön.
TypeScript React -projektin aloittaminen
Create React Appin käyttö
Helpoin tapa aloittaa uusi TypeScript React -projekti on käyttää Create React Appia TypeScript-mallipohjan kanssa:
npx create-react-app my-typescript-react-app --template typescript
Tämä komento luo perusmuotoisen React-projektin, jossa TypeScript on valmiiksi määritetty, sisältäen tarvittavat riippuvuudet ja tsconfig.json
-tiedoston.
tsconfig.json
-tiedoston konfigurointi
tsconfig.json
-tiedosto on TypeScript-konfiguraatiosi ydin. Tässä on joitakin suositeltuja asetuksia:
{
"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"
]
}
Tärkeitä huomioitavia asetuksia:
"strict": true
: Ottaa käyttöön tiukan tyyppitarkistuksen, mikä on erittäin suositeltavaa mahdollisten virheiden havaitsemiseksi."esModuleInterop": true
: Mahdollistaa yhteentoimivuuden CommonJS- ja ES-moduulien välillä."jsx": "react-jsx"
: Ottaa käyttöön uuden JSX-muunnoksen, joka yksinkertaistaa React-koodia ja parantaa suorituskykyä.
Parhaat käytännöt React-komponenteille TypeScriptin kanssa
Komponenttien propsien tyypitys
Yksi tärkeimmistä asioista TypeScriptin käytössä Reactin kanssa on komponenttien propsien oikea tyypitys. Käytä rajapintoja (interface) tai tyyppialiaksia (type) määritelläksesi props-objektin muodon.
interface MyComponentProps {
name: string;
age?: number; // Valinnainen prop
onClick: () => void;
}
const MyComponent: React.FC = ({ name, age, onClick }) => {
return (
Hei, {name}!
{age && Olet {age} vuotta vanha.
}
);
};
Käyttämällä React.FC<MyComponentProps>
varmistetaan, että komponentti on funktionaalinen komponentti ja että sen propsit on tyypitetty oikein.
Komponentin tilan (state) tyypitys
Jos käytät luokkakomponentteja, sinun on myös tyypitettävä komponentin tila (state). Määrittele rajapinta tai tyyppialias tilaobjektille ja käytä sitä komponentin määrittelyssä.
interface MyComponentState {
count: number;
}
class MyComponent extends React.Component<{}, MyComponentState> {
state: MyComponentState = {
count: 0
};
handleClick = () => {
this.setState({
count: this.state.count + 1
});
};
render() {
return (
Määrä: {this.state.count}
);
}
}
Funktionaalisissa komponenteissa, jotka käyttävät useState
-hookia, TypeScript pystyy usein päättelemään tilamuuttujan tyypin, mutta voit myös määrittää sen eksplisiittisesti:
import React, { useState } from 'react';
const MyComponent: React.FC = () => {
const [count, setCount] = useState<number>(0);
return (
Määrä: {count}
);
};
Tyyppivartijoiden (Type Guards) käyttö
Tyyppivartijat ovat funktioita, jotka rajaavat muuttujan tyyppiä tietyssä laajuudessa (scope). Ne ovat hyödyllisiä käsiteltäessä union-tyyppejä tai kun on varmistettava, että muuttujalla on tietty tyyppi ennen operaation suorittamista.
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
-funktio on tyyppivartija, joka tarkistaa, onko Shape
-tyyppinen muuttuja Circle
. if
-lohkossa TypeScript tietää, että shape
on Circle
ja antaa sinun käyttää sen radius
-ominaisuutta.
Tapahtumien käsittely
Käsiteltäessä tapahtumia Reactissa TypeScriptin kanssa on tärkeää tyypittää tapahtumaobjekti oikein. Käytä sopivaa tapahtumatyyppiä React
-nimiavaruudesta.
const MyComponent: React.FC = () => {
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
console.log(event.target.value);
};
return (
);
};
Tässä esimerkissä React.ChangeEvent<HTMLInputElement>
käytetään tyypittämään input-elementin change-tapahtuman tapahtumaobjekti. Tämä antaa pääsyn target
-ominaisuuteen, joka on tyyppiä HTMLInputElement
.
Projektirakenne
Hyvin jäsennelty projekti on ratkaisevan tärkeä ylläpidettävyyden ja skaalautuvuuden kannalta. Tässä on ehdotus projektirakenteeksi TypeScript React -sovellukselle:
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
Avainkohdat:
- Components: Ryhmittele toisiinsa liittyvät komponentit hakemistoihin. Jokaisen hakemiston tulisi sisältää komponentin TypeScript-tiedosto, CSS-moduulit (jos käytössä) ja
index.ts
-tiedosto komponentin exporttaamista varten. - Pages: Tallenna tänne ylätason komponentit, jotka edustavat sovelluksesi eri sivuja.
- Services: Toteuta API-kutsut ja muut palvelut tässä hakemistossa.
- Types: Määrittele globaalit tyyppimäärittelyt ja rajapinnat tässä hakemistossa.
- Utils: Tallenna aputoiminnot ja vakiot.
- index.ts: Käytä
index.ts
-tiedostoja moduulien uudelleen-exporttaamiseen hakemistosta, mikä tarjoaa siistin ja organisoidun API:n moduulien importtaamiseen.
Hookien käyttö TypeScriptin kanssa
React Hookit mahdollistavat tilan ja muiden React-ominaisuuksien käytön funktionaalisissa komponenteissa. TypeScript toimii saumattomasti Hookien kanssa tarjoten tyyppiturvallisuutta ja paremman kehittäjäkokemuksen.
useState
Kuten aiemmin näytettiin, voit eksplisiittisesti tyypittää tilamuuttujan käyttäessäsi useState
-hookia:
import React, { useState } from 'react';
const MyComponent: React.FC = () => {
const [count, setCount] = useState<number>(0);
return (
Määrä: {count}
);
};
useEffect
Käytettäessä useEffect
-hookia, ole tarkkana riippuvuustaulukon (dependency array) kanssa. TypeScript voi auttaa sinua havaitsemaan virheitä, jos unohdat sisällyttää riippuvuuden, jota käytetään efektin sisällä.
import React, { useState, useEffect } from 'react';
const MyComponent: React.FC = () => {
const [count, setCount] = useState<number>(0);
useEffect(() => {
document.title = `Määrä: ${count}`;
}, [count]); // Lisää 'count' riippuvuustaulukkoon
return (
Määrä: {count}
);
};
Jos jätät count
-muuttujan pois riippuvuustaulukosta, efekti suoritetaan vain kerran komponentin latautuessa, eikä dokumentin otsikko päivity määrän muuttuessa. TypeScript varoittaa sinua tästä mahdollisesta ongelmasta.
useContext
Käytettäessä useContext
-hookia, sinun on annettava tyyppi kontekstin arvolle.
import React, { createContext, useContext } from 'react';
interface ThemeContextType {
theme: string;
toggleTheme: () => void;
}
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
const ThemeProvider: React.FC = ({ children }) => {
// Toteuta teemalogiikka tähän
return (
{} }}>
{children}
);
};
const MyComponent: React.FC = () => {
const { theme, toggleTheme } = useContext(ThemeContext) as ThemeContextType;
return (
Teema: {theme}
);
};
export { ThemeProvider, MyComponent };
Määrittämällä tyypin kontekstin arvolle varmistat, että useContext
-hook palauttaa oikean tyyppisen arvon.
TypeScript React -komponenttien testaaminen
Testaus on olennainen osa vankkojen sovellusten rakentamista. TypeScript parantaa testausta tarjoamalla tyyppiturvallisuutta ja parempaa koodikattavuutta.
Yksikkötestaus
Käytä testauskehyksiä, kuten Jest ja React Testing Library, komponenttiesi yksikkötestaamiseen.
// MyComponent.test.tsx
import React from 'react';
import { render, screen, fireEvent } from '@testing-library/react';
import MyComponent from './MyComponent';
describe('MyComponent', () => {
it('renderöi komponentin oikealla nimellä', () => {
render(<MyComponent name="John" onClick={() => {}} />);
expect(screen.getByText('Hei, John!')).toBeInTheDocument();
});
it('kutsuu onClick-käsittelijää, kun painiketta klikataan', () => {
const onClick = jest.fn();
render(<MyComponent name="John" onClick={onClick} />);
fireEvent.click(screen.getByRole('button'));
expect(onClick).toHaveBeenCalledTimes(1);
});
});
TypeScriptin tyyppitarkistus auttaa löytämään virheitä testeistäsi, kuten väärien propsien välittämisen tai väärien tapahtumankäsittelijöiden käytön.
Integraatiotestaus
Integraatiotestit varmistavat, että sovelluksesi eri osat toimivat oikein yhdessä. Käytä työkaluja, kuten Cypress tai Playwright, päästä-päähän-testaukseen (end-to-end).
Suorituskyvyn optimointi
TypeScript voi myös auttaa suorituskyvyn optimoinnissa havaitsemalla potentiaalisia suorituskyvyn pullonkauloja varhaisessa kehitysvaiheessa.
Memoisaatio
Käytä React.memo
-funktiota funktionaalisten komponenttien memoisaatioon ja tarpeettomien uudelleenrenderöintien estämiseen.
import React from 'react';
interface MyComponentProps {
name: string;
}
const MyComponent: React.FC<MyComponentProps> = ({ name }) => {
console.log('Renderöidään MyComponent');
return (
Hei, {name}!
);
};
export default React.memo(MyComponent);
React.memo
renderöi komponentin uudelleen vain, jos sen propsit ovat muuttuneet. Tämä voi parantaa suorituskykyä merkittävästi, erityisesti monimutkaisissa komponenteissa.
Koodin pilkkominen (Code Splitting)
Käytä dynaamisia import-lausekkeita pilkkoaksesi koodisi pienempiin osiin ja ladataksesi ne tarvittaessa. Tämä voi lyhentää sovelluksesi alkuperäistä latausaikaa.
import React, { Suspense } from 'react';
const MyComponent = React.lazy(() => import('./MyComponent'));
const App: React.FC = () => {
return (
);
};
React.lazy
mahdollistaa komponenttien dynaamisen tuonnin, jolloin ne ladataan vasta kun niitä tarvitaan. Suspense
-komponentti tarjoaa varakäyttöliittymän komponentin latauksen ajaksi.
Yhteenveto
TypeScriptin käyttö Reactin kanssa voi merkittävästi parantaa verkkosovellustesi laatua, ylläpidettävyyttä ja skaalautuvuutta. Noudattamalla näitä parhaita käytäntöjä voit hyödyntää TypeScriptin tehoa rakentaaksesi vakaita ja suorituskykyisiä sovelluksia, jotka vastaavat maailmanlaajuisen yleisön tarpeisiin. Muista keskittyä selkeisiin tyyppimäärittelyihin, hyvin jäsenneltyyn projektiorganisaatioon ja perusteelliseen testaukseen varmistaaksesi projektiesi pitkän aikavälin menestyksen.