Impostazione di TypeScript per progetti React moderni utilizzando Webpack

Pubblicato: 2022-03-10
Riepilogo rapido ↬ Questo articolo introduce Typescript, un apice di JavaScript che presenta la funzionalità di tipo statico per individuare gli errori comuni nei codici degli sviluppatori, che migliora le prestazioni, quindi si traduce in robuste applicazioni aziendali. Imparerai anche come configurare in modo efficiente TypeScript in un progetto React mentre creiamo un'app Money Heist Episode Picker, esplorando TypeScript, hook React come useReducer, useContext e Reach Router.

In questa era di sviluppo software, JavaScript può essere utilizzato per sviluppare quasi tutti i tipi di app. Tuttavia, il fatto che JavaScript sia digitato dinamicamente potrebbe essere un problema per la maggior parte delle grandi aziende, a causa della sua funzionalità di controllo del tipo allentata.

Fortunatamente, non dobbiamo aspettare che l'Ecma Technical Committee 39 introduca un sistema di tipi statici in JavaScript. Possiamo invece usare TypeScript.

JavaScript, essendo digitato dinamicamente, non è a conoscenza del tipo di dati di una variabile finché tale variabile non viene istanziata in fase di esecuzione. Gli sviluppatori che scrivono programmi software di grandi dimensioni potrebbero avere la tendenza a riassegnare una variabile, dichiarata in precedenza, a un valore di tipo diverso, senza alcun avviso o problema di sorta, con conseguente bug spesso trascurato.

In questo tutorial impareremo cos'è TypeScript e come lavorarci in un progetto React. Alla fine, avremo creato un progetto composto da un'app per la selezione di episodi per il programma TV Money Heist , utilizzando TypeScript e gli attuali hook simili a React ( useState , useEffect , useReducer , useContext ). Con questa conoscenza, puoi continuare a sperimentare TypeScript nei tuoi progetti.

Questo articolo non è un'introduzione a TypeScript. Quindi, non esamineremo la sintassi di base di TypeScript e JavaScript. Tuttavia, non devi essere un esperto in nessuna di queste lingue per seguire, perché cercheremo di seguire il principio KISS (mantienilo semplice, stupido).

Altro dopo il salto! Continua a leggere sotto ↓

Che cos'è TypeScript?

Nel 2019, TypeScript è stata classificata come la settima lingua più utilizzata e la quinta lingua in più rapida crescita su GitHub. Ma cos'è esattamente TypeScript?

Secondo la documentazione ufficiale, TypeScript è un superset tipizzato di JavaScript che viene compilato in JavaScript semplice. È sviluppato e gestito da Microsoft e dalla comunità open source.

"Superset" in questo contesto significa che il linguaggio contiene tutte le caratteristiche e le funzionalità di JavaScript e poi alcune. TypeScript è un linguaggio di scripting tipizzato.

Offre agli sviluppatori un maggiore controllo sulla propria base di codice tramite l'annotazione del tipo, le classi e l'interfaccia, evitando agli sviluppatori di dover correggere manualmente fastidiosi bug nella console.

TypeScript non è stato creato per alterare JavaScript. Invece, espande JavaScript con nuove preziose funzionalità. Qualsiasi programma scritto in JavaScript semplice verrà eseguito anche come previsto in TypeScript, comprese le app mobili multipiattaforma e i back-end in Node.js.

Ciò significa che puoi anche scrivere app React in TypeScript, come faremo in questo tutorial.

Perché dattiloscritto?

Forse non sei convinto di abbracciare la bontà di TypeScript. Consideriamo alcuni dei suoi vantaggi.

Meno bug

Non possiamo eliminare tutti i bug nel nostro codice, ma possiamo ridurli. TypeScript controlla i tipi in fase di compilazione e genera errori se il tipo di variabile cambia.

Essere in grado di trovare questi errori evidenti ma frequenti così presto rende molto più semplice gestire il codice con i tipi.

Il refactoring è più facile

Probabilmente vuoi spesso rifattorizzare un bel po' di cose, ma poiché toccano così tanto altro codice e molti altri file, sei cauto nel modificarli.

In TypeScript, queste cose possono spesso essere rifattorizzato con un semplice clic del comando "Rinomina simbolo" nel tuo ambiente di sviluppo integrato (IDE).

Rinominare l'app in expApp (anteprima grande)

In un linguaggio tipizzato dinamicamente come JavaScript, l'unico modo per refactoring di più file contemporaneamente è con la tradizionale funzione "cerca e sostituisci" utilizzando espressioni regolari (RegExp).

In un linguaggio digitato staticamente come TypeScript, "cerca e sostituisci" non è più necessario. Con i comandi IDE come "Trova tutte le occorrenze" e "Rinomina simbolo", puoi vedere tutte le occorrenze nell'app della funzione, classe o proprietà specificata di un'interfaccia oggetto.

TypeScript ti aiuterà a trovare tutte le istanze del bit rifattorizzato, rinominarlo e avvisarti con un errore di compilazione nel caso in cui il tuo codice abbia dei tipi non corrispondenti dopo il refactoring.

TypeScript ha ancora più vantaggi di quelli che abbiamo trattato qui.

Svantaggi di TypeScript

TypeScript non è sicuramente privo di svantaggi, anche date le promettenti funzionalità evidenziate sopra.

Un falso senso di sicurezza

La funzione di controllo del tipo di TypeScript crea spesso un falso senso di sicurezza tra gli sviluppatori. Il controllo del tipo ci avverte infatti quando qualcosa non va nel nostro codice. Tuttavia, i tipi statici non riducono la densità complessiva dei bug.

Pertanto, la forza del tuo programma dipenderà dal tuo utilizzo di TypeScript, perché i tipi sono scritti dallo sviluppatore e non controllati in fase di esecuzione.

Se stai cercando TypeScript per ridurre i tuoi bug, considera invece lo sviluppo basato su test.

Sistema di digitazione complicato

Il sistema di digitazione, sebbene sia un ottimo strumento sotto molti aspetti, a volte può essere un po' complicato. Questo svantaggio deriva dal fatto che è completamente interoperabile con JavaScript, il che lascia ancora più spazio alle complicazioni.

Tuttavia, TypeScript è ancora JavaScript, quindi è importante comprendere JavaScript.

Quando usare TypeScript?

Ti consiglierei di usare TypeScript nei seguenti casi:

  • Se stai cercando di creare un'applicazione che verrà mantenuta per un lungo periodo , ti consiglio vivamente di iniziare con TypeScript, perché promuove l'autodocumentazione del codice, aiutando così gli altri sviluppatori a capire facilmente il tuo codice quando si uniscono alla tua base di codice .
  • Se devi creare una libreria , considera di scriverla in TypeScript. Aiuterà gli editor di codice a suggerire i tipi appropriati agli sviluppatori che stanno usando la tua libreria.

Nelle ultime sezioni, abbiamo bilanciato i pro ei contro di TypeScript. Passiamo all'attività del giorno: impostare TypeScript in un moderno progetto React .

Iniziare

Esistono diversi modi per impostare TypeScript in un progetto React. In questo tutorial, ne tratteremo solo due.

Metodo 1: crea l'app React + TypeScript

Circa due anni fa, il team React ha rilasciato Create React App 2.1, con supporto TypeScript. Quindi, potresti non dover mai fare alcun lavoro pesante per inserire TypeScript nel tuo progetto.

Annuncio di TypeScript nell'app Create React (anteprima grande)

Per avviare un nuovo progetto Create React App, puoi eseguire questo...

 npx create-react-app my-app --folder-name

… o questo:

 yarn create react-app my-app --folder-name

Per aggiungere TypeScript a un progetto Create React App, prima installarlo e i rispettivi @types :

 npm install --save typescript @types/node @types/react @types/react-dom @types/jest

… o:

 yarn add typescript @types/node @types/react @types/react-dom @types/jest

Quindi, rinomina i file (ad esempio, index.js in index.tsx ) e riavvia il server di sviluppo !

È stato veloce, vero?

Metodo 2: imposta TypeScript con Webpack

Webpack è un bundler di moduli statici per applicazioni JavaScript. Prende tutto il codice dalla tua applicazione e lo rende utilizzabile in un browser web. I moduli sono blocchi di codice riutilizzabili creati da JavaScript, node_modules , immagini e stili CSS della tua app, che sono pacchettizzati per essere facilmente utilizzati sul tuo sito web.

Crea un nuovo progetto

Iniziamo creando una nuova directory per il nostro progetto:

 mkdir react-webpack cd react-webpack

Useremo npm per inizializzare il nostro progetto:

 npm init -y

Il comando precedente genererà un file package.json con alcuni valori predefiniti. Aggiungiamo anche alcune dipendenze per webpack, TypeScript e alcuni moduli specifici di React.

Installazione di pacchetti

Infine, dovremmo installare i pacchetti necessari. Apri la tua interfaccia della riga di comando (CLI) ed esegui questo:

 #Installing devDependencies npm install --save-dev @types/react @types/react-dom awesome-typescript-loader css-loader html-webpack-plugin mini-css-extract-plugin source-map-loader typescript webpack webpack-cli webpack-dev-server #installing Dependencies npm install react react-dom

Aggiungiamo anche manualmente alcuni file e cartelle diversi nella nostra cartella react-webpack :

  1. Aggiungi webpack.config.js per aggiungere configurazioni relative al webpack.
  2. Aggiungi tsconfig.json per tutte le nostre configurazioni TypeScript.
  3. Aggiungi una nuova directory, src .
  4. Crea una nuova directory, components , nella cartella src .
  5. Infine, aggiungi index.html , App.tsx e index.tsx nella cartella dei components .

Struttura del progetto

Pertanto, la nostra struttura di cartelle sarà simile a questa:

 ├── package.json ├── package-lock.json ├── tsconfig.json ├── webpack.config.js ├── .gitignore └── src └──components ├── App.tsx ├── index.tsx ├── index.html

Inizia ad aggiungere del codice

Inizieremo con index.html :

 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>React-Webpack Setup</title> </head> <body> <div></div> </body> </html>

Questo creerà l'HTML, con un div vuoto con un ID di output .

Aggiungiamo il codice al nostro componente React App.tsx :

 import * as React from "react"; export interface HelloWorldProps { userName: string; lang: string; } export const App = (props: HelloWorldProps) => ( <h1> Hi {props.userName} from React! Welcome to {props.lang}! </h1> );

Abbiamo creato un oggetto interfaccia e lo abbiamo chiamato HelloWorldProps , con userName e lang aventi un tipo di string .

Abbiamo passato gli props di scena al nostro componente App e l'abbiamo esportato.

Ora, aggiorniamo il codice in index.tsx :

 import * as React from "react"; import * as ReactDOM from "react-dom"; import { App } from "./App"; ReactDOM.render( <App userName="Beveloper" lang="TypeScript" />, document.getElementById("output") );

Abbiamo appena importato il componente App in index.tsx . Quando webpack vede qualsiasi file con l'estensione .ts o .tsx , trasporterà quel file usando la libreria awesome-typescript-loader.

Configurazione dattiloscritta

Aggiungeremo quindi alcune configurazioni a tsconfig.json :

 { "compilerOptions": { "jsx": "react", "module": "commonjs", "noImplicitAny": true, "outDir": "./build/", "preserveConstEnums": true, "removeComments": true, "sourceMap": true, "target": "es5" }, "include": [ "src/components/index.tsx" ] }

Diamo anche un'occhiata alle diverse opzioni che abbiamo aggiunto a tsconfig.json :

  • compilerOptions Rappresenta le diverse opzioni del compilatore.
  • jsx:react Aggiunge il supporto per JSX nei file .tsx .
  • lib Aggiunge un elenco di file di libreria alla compilation (ad esempio, l'utilizzo di es2015 consente di utilizzare la sintassi ECMAScript 6).
  • module Genera il codice del modulo.
  • noImplicitAny Solleva errori per dichiarazioni con un any tipo implicito.
  • outDir Rappresenta la directory di output.
  • sourceMap Genera un file .map , che può essere molto utile per il debug dell'app.
  • target Rappresenta la versione ECMAScript di destinazione in cui transpilare il nostro codice (possiamo aggiungere una versione in base ai nostri requisiti specifici del browser).
  • include Utilizzato per specificare l'elenco di file da includere.

Configurazione del pacchetto web

Aggiungiamo alcune configurazioni di webpack a webpack.config.js .

 const path = require("path"); const HtmlWebpackPlugin = require("html-webpack-plugin"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); module.exports = { entry: "./src/components/index.tsx", target: "web", mode: "development", output: { path: path.resolve(\__dirname, "build"), filename: "bundle.js", }, resolve: { extensions: [".js", ".jsx", ".json", ".ts", ".tsx"], }, module: { rules: [ { test: /\.(ts|tsx)$/, loader: "awesome-typescript-loader", }, { enforce: "pre", test: /\.js$/, loader: "source-map-loader", }, { test: /\.css$/, loader: "css-loader", }, ], }, plugins: [ new HtmlWebpackPlugin({ template: path.resolve(\__dirname, "src", "components", "index.html"), }), new MiniCssExtractPlugin({ filename: "./src/yourfile.css", }), ], };

Diamo un'occhiata alle diverse opzioni che abbiamo aggiunto a webpack.config.js :

  • entry Questo specifica il punto di ingresso per la nostra app. Potrebbe essere un singolo file o una matrice di file che vogliamo includere nella nostra build.
  • output Contiene la configurazione dell'output. L'app lo esamina quando si tenta di inviare il codice in bundle dal nostro progetto al disco. Il percorso rappresenta la directory di output in cui inviare il codice e il nome file rappresenta il nome file dello stesso. È generalmente chiamato bundle.js .
  • resolve Webpack esamina questo attributo per decidere se raggruppare o saltare il file. Pertanto, nel nostro progetto, webpack considererà i file con le estensioni .js , .jsx , .json , .ts e .tsx per il raggruppamento.
  • module Possiamo abilitare il webpack per caricare un file particolare quando richiesto dall'app, utilizzando i caricatori. Prende un oggetto rules che specifica che:
    • qualsiasi file che termina con l'estensione .tsx o .ts dovrebbe utilizzare awesome-typescript-loader di caratteri impressionante per essere caricato;
    • i file che terminano con l'estensione .js devono essere caricati con source-map-loader ;
    • i file che terminano con l'estensione .css devono essere caricati con css-loader .
  • plugins Webpack ha i suoi limiti e fornisce plugin per superarli ed estendere le sue capacità. Ad esempio, html-webpack-plugin crea un file modello di cui viene eseguito il rendering nel browser dal file index.html nella directory ./src/component/index.html .

MiniCssExtractPlugin il rendering del file CSS padre dell'app.

Aggiunta di script a package.json

Possiamo aggiungere diversi script per creare app React nel nostro file package.json :

 "scripts": { "start": "webpack-dev-server --open", "build": "webpack" },

Ora, esegui npm start nella tua CLI. Se è andato tutto bene, dovresti vedere questo:

Output di configurazione di React-Webpack (anteprima grande)

Se hai un talento per il webpack, clona il repository per questa configurazione e usalo nei tuoi progetti.

Creazione di file

Crea una cartella src e un file index.tsx . Questo sarà il file di base che esegue il rendering di React.

Ora, se eseguiamo npm start , eseguirà il nostro server e aprirà una nuova scheda. L'esecuzione npm run build creerà il webpack per la produzione e creerà una cartella di build per noi.

Abbiamo visto come configurare TypeScript da zero utilizzando l'app Create React e il metodo di configurazione del webpack.

Uno dei modi più rapidi per ottenere una conoscenza completa di TypeScript è convertire uno dei tuoi progetti vanilla React esistenti in TypeScript. Sfortunatamente, l'adozione incrementale di TypeScript in un progetto Vanilla React esistente è stressante perché comporta la necessità di espellere o rinominare tutti i file, il che comporterebbe conflitti e una richiesta pull gigante se il progetto appartenesse a un team di grandi dimensioni.

Successivamente, vedremo come migrare facilmente un progetto React in TypeScript.

Migrare un'app Create React esistente in TypeScript

Per rendere questo processo più gestibile, lo suddivideremo in passaggi, che ci consentiranno di migrare in singoli blocchi. Ecco i passaggi che adotteremo per migrare il nostro progetto:

  1. Aggiungi TypeScript e tipi.
  2. Aggiungi tsconfig.json .
  3. Inizia in piccolo.
  4. Rinomina l'estensione dei file in .tsx .

1. Aggiungi TypeScript al progetto

Innanzitutto, dovremo aggiungere TypeScript al nostro progetto. Supponendo che il tuo progetto React sia stato avviato con Create React App, possiamo eseguire quanto segue:

 # Using npm npm install --save typescript @types/node @types/react @types/react-dom @types/jest # Using Yarn yarn add typescript @types/node @types/react @types/react-dom @types/jest

Si noti che non abbiamo ancora cambiato nulla in TypeScript. Se eseguiamo il comando per avviare il progetto in locale ( npm start o yarn start ), non cambia nulla. Se questo è il caso, allora fantastico! Siamo pronti per il prossimo passo.

2. Aggiungi il file tsconfig.json

Prima di sfruttare TypeScript, dobbiamo configurarlo tramite il file tsconfig.json . Il modo più semplice per iniziare è impalcarne uno usando questo comando:

 npx tsc --init

Questo ci fornisce alcune nozioni di base, con molto codice commentato. Ora, sostituisci tutto il codice in tsconfig.json con questo:

 { "compilerOptions": { "jsx": "react", "module": "commonjs", "noImplicitAny": true, "outDir": "./build/", "preserveConstEnums": true, "removeComments": true, "sourceMap": true, "target": "es5" }, "include": [ "./src/**/**/\*" ] }

Configurazione dattiloscritta

Diamo anche un'occhiata alle diverse opzioni che abbiamo aggiunto a tsconfig.json :

  • compilerOptions Rappresenta le diverse opzioni del compilatore.
    • target Traduce i costrutti JavaScript più recenti in una versione precedente, come ECMAScript 5.
    • lib Aggiunge un elenco di file di libreria alla compilation (ad esempio, l'utilizzo di es2015 consente di utilizzare la sintassi ECMAScript 6).
    • jsx:react Aggiunge il supporto per JSX nei file .tsx .
    • lib Aggiunge un elenco di file di libreria alla compilation (ad esempio, l'utilizzo di es2015 consente di utilizzare la sintassi ECMAScript 6).
    • module Genera il codice del modulo.
    • noImplicitAny Utilizzato per generare errori per dichiarazioni con un tipo implicito any .
    • outDir Rappresenta la directory di output.
    • sourceMap Genera un file .map , che può essere molto utile per il debug della nostra app.
    • include Utilizzato per specificare l'elenco di file da includere.

Le opzioni di configurazione variano in base alla richiesta di un progetto. Potrebbe essere necessario controllare il foglio di calcolo delle opzioni di TypeScript per capire cosa si adatta al tuo progetto.

Abbiamo intrapreso solo le azioni necessarie per preparare le cose. Il nostro prossimo passo è migrare un file in TypeScript.

3. Inizia con un componente semplice

Approfitta della capacità di TypeScript di essere adottato gradualmente. Vai un file alla volta al tuo ritmo. Fai ciò che ha senso per te e il tuo team. Non cercare di affrontarlo tutto in una volta.

Per convertirlo correttamente, dobbiamo fare due cose:

  1. Cambia l'estensione del file in .tsx .
  2. Aggiungi l'annotazione del tipo (che richiederebbe una certa conoscenza di TypeScript).

4. Rinominare le estensioni dei file in .tsx

In una grande base di codice, potrebbe sembrare faticoso rinominare i file singolarmente.

Rinomina più file su macOS

Rinominare più file può essere una perdita di tempo. Ecco come puoi farlo su un Mac. Fai clic con il pulsante destro del mouse (o Ctrl + clic, oppure fai clic con due dita contemporaneamente sul trackpad se stai utilizzando un MacBook) sulla cartella che contiene i file che desideri rinominare. Quindi, fai clic su "Rivela nel Finder". Nel Finder, seleziona tutti i file che desideri rinominare. Fai clic con il pulsante destro del mouse sui file selezionati e scegli "Rinomina X elementi..." Quindi vedrai qualcosa del genere:

Rinomina i file su un Mac (Anteprima grande)

Inserisci la stringa che vuoi trovare e la stringa con cui vuoi sostituire quella stringa trovata e premi "Rinomina". Fatto.

Rinomina più file su Windows

La ridenominazione di più file su Windows va oltre lo scopo di questo tutorial, ma è disponibile una guida completa. Di solito si ottengono errori dopo aver rinominato i file; devi solo aggiungere le annotazioni del tipo. Puoi rispolverare questo nella documentazione.

Abbiamo spiegato come configurare TypeScript in un'app React. Ora creiamo un'app per la selezione di episodi per Money Heist usando TypeScript.

Non tratteremo i tipi di base di TypeScript. È necessario esaminare la documentazione prima di continuare in questo tutorial.

Tempo per costruire

Per rendere questo processo meno scoraggiante, lo suddivideremo in passaggi, che ci consentiranno di creare l'app in singoli blocchi. Ecco tutti i passaggi che adotteremo per creare il selettore di episodi di Money Heist :

  • Impalcatura di un'app Create React.
  • Recupera episodi.
    • Crea i tipi e le interfacce appropriati per i nostri episodi in interface.ts .
    • Configura il negozio per il recupero degli episodi in store.tsx .
    • Crea l'azione per il recupero degli episodi in action.ts .
    • Crea un componente EpisodeList.tsx che contenga gli episodi recuperati.
    • Importa il componente EpisodesList nella nostra home page usando React Lazy and Suspense .
  • Aggiungi episodi.
    • Configura store per aggiungere episodi in store.tsx .
    • Crea l'azione per aggiungere episodi in action.ts .
  • Rimuovi episodi.
    • Configura lo store per eliminare gli episodi in store.tsx .
    • Crea l'azione per eliminare gli episodi in action.ts .
  • Episodio preferito.
    • Importa il componente EpisodesList nell'episodio preferito.
    • Render EpisodesList all'interno dell'episodio preferito.
  • Utilizzo di Reach Router per la navigazione.

Imposta Reagire

Il modo più semplice per configurare React è utilizzare l'app Crea React. Create React App è un modo ufficialmente supportato per creare applicazioni React a pagina singola. Offre una configurazione di build moderna senza configurazione.

Ne faremo uso per avviare l'applicazione che andremo a costruire. Dalla tua CLI, esegui il comando seguente:

 npx create-react-app react-ts-app && cd react-ts-app

Una volta completata l'installazione, avviare il server React eseguendo npm start .

Pagina iniziale di React (Anteprima grande)

Comprensione di interfacce e tipi in dattiloscritto

Le interfacce in TypeScript vengono utilizzate quando è necessario assegnare tipi alle proprietà degli oggetti. Quindi, useremmo le interfacce per definire i nostri tipi.

 interface Employee { name: string, role: string salary: number } const bestEmployee: Employee= { name: 'John Doe', role: 'IOS Developer', salary: '$8500' //notice we are using a string }

Durante la compilazione del codice sopra, vedremmo questo errore: “I tipi di salary di proprietà sono incompatibili. La string di tipo non è assegnabile al number di tipo."

Tali errori si verificano in TypeScript quando a una proprietà oa una variabile viene assegnato un tipo diverso dal tipo definito. In particolare, lo snippet sopra indica che alla proprietà salary è stato assegnato un tipo string anziché un tipo number .

Creiamo un file interface.ts nella nostra cartella src . Copia e incolla questo codice al suo interno:

 /** |-------------------------------------------------- | All the interfaces! |-------------------------------------------------- */ export interface IEpisode { airdate: string airstamp: string airtime: string id: number image: { medium: string; original: string } name: string number: number runtime: number season: number summary: string url: string } export interface IState { episodes: Array<IEpisode> favourites: Array<IEpisode> } export interface IAction { type: string payload: Array<IEpisode> | any } export type Dispatch = React.Dispatch<IAction> export type FavAction = ( state: IState, dispatch: Dispatch, episode: IEpisode ) => IAction export interface IEpisodeProps { episodes: Array<IEpisode> store: { state: IState; dispatch: Dispatch } toggleFavAction: FavAction favourites: Array<IEpisode> } export interface IProps { episodes: Array<IEpisode> store: { state: IState; dispatch: Dispatch } toggleFavAction: FavAction favourites: Array<IEpisode> }

È buona norma aggiungere una "I" al nome dell'interfaccia. Rende il codice leggibile. Tuttavia, potresti decidere di escluderlo.

Interfaccia IEpisode

La nostra API restituisce un insieme di proprietà come airdate , airstamp , airtime , id , image , name , number , runtime , season , summary e url . Quindi, abbiamo definito un'interfaccia IEpisode e impostato i tipi di dati appropriati sulle proprietà dell'oggetto.

Interfaccia IState

La nostra interfaccia IState ha rispettivamente le proprietà degli episodes e favorites e un'interfaccia Array<IEpisode> .

Iazione

Le proprietà dell'interfaccia IAction sono payload e type . La proprietà type ha un tipo stringa, mentre il payload ha un tipo Array | any Array | any .

Si noti che Array | any Array | any significa un array dell'interfaccia dell'episodio o qualsiasi tipo.

Il tipo di Dispatch è impostato su React.Dispatch e un'interfaccia <IAction> . Si noti che React.Dispatch è il tipo standard per la funzione di dispatch , in base alla base di codice @types/react , mentre <IAction> è un array dell'azione Interface.

Inoltre, Visual Studio Code ha un correttore TypeScript. Quindi, semplicemente evidenziando o passando sopra il codice, è abbastanza intelligente suggerire il tipo appropriato.

In altre parole, per poter utilizzare la nostra interfaccia nelle nostre app, dobbiamo esportarla. Finora, abbiamo il nostro negozio e le nostre interfacce che contengono il tipo del nostro oggetto. Creiamo ora il nostro negozio. Si noti che le altre interfacce seguono le stesse convenzioni di quelle spiegate.

Recupera episodi

Creazione di un negozio

Per recuperare i nostri episodi, abbiamo bisogno di un archivio che contenga lo stato iniziale dei dati e che definisca la nostra funzione di riduzione.

Useremo useReducer hook per configurarlo. Crea un file store.tsx nella tua cartella src . Copia e incolla il codice seguente al suo interno.

 import React, { useReducer, createContext } from 'react' import { IState, IAction } from './types/interfaces' const initialState: IState = { episodes: [], favourites: [] } export const Store = createContext (initialState) const reducer = (state: IState, action: IAction): IState => { switch (action.type) { case 'FETCH_DATA': return { ...state, episodes: action.payload } default: return state } } export const StoreProvider = ({ children }: JSX.ElementChildrenAttribute): JSX.Element => { const [state, dispatch] = useReducer(reducer, initialState) return {children} } import React, { useReducer, createContext } from 'react' import { IState, IAction } from './types/interfaces' const initialState: IState = { episodes: [], favourites: [] } export const Store = createContext (initialState) const reducer = (state: IState, action: IAction): IState => { switch (action.type) { case 'FETCH_DATA': return { ...state, episodes: action.payload } default: return state } } export const StoreProvider = ({ children }: JSX.ElementChildrenAttribute): JSX.Element => { const [state, dispatch] = useReducer(reducer, initialState) return {children} } import React, { useReducer, createContext } from 'react' import { IState, IAction } from './types/interfaces' const initialState: IState = { episodes: [], favourites: [] } export const Store = createContext (initialState) const reducer = (state: IState, action: IAction): IState => { switch (action.type) { case 'FETCH_DATA': return { ...state, episodes: action.payload } default: return state } } export const StoreProvider = ({ children }: JSX.ElementChildrenAttribute): JSX.Element => { const [state, dispatch] = useReducer(reducer, initialState) return {children} } import React, { useReducer, createContext } from 'react' import { IState, IAction } from './types/interfaces' const initialState: IState = { episodes: [], favourites: [] } export const Store = createContext (initialState) const reducer = (state: IState, action: IAction): IState => { switch (action.type) { case 'FETCH_DATA': return { ...state, episodes: action.payload } default: return state } } export const StoreProvider = ({ children }: JSX.ElementChildrenAttribute): JSX.Element => { const [state, dispatch] = useReducer(reducer, initialState) return {children} }

Di seguito sono riportati i passaggi che abbiamo adottato per creare il negozio:

  • Per definire il nostro negozio, abbiamo bisogno useReducer e dell'API createContext di React, motivo per cui l'abbiamo importato.
  • Abbiamo importato IState e IAction da ./types/interfaces .
  • Abbiamo dichiarato un oggetto initialState con un tipo IState e le proprietà degli episodi e dei preferiti, che sono entrambi impostati rispettivamente su un array vuoto.
  • Successivamente, abbiamo creato una variabile Store che contiene il metodo createContext e a cui viene passato initialState .

Il tipo di metodo createContext è <IState | any> <IState | any> , il che significa che potrebbe essere un tipo di <IState> o any . Vedremo any tipo usato spesso in questo articolo.

  • Successivamente, abbiamo dichiarato una funzione reducer e passato state e action come parametri. La funzione reducer ha un'istruzione switch che controlla il valore di action.type . Se il valore è FETCH_DATA , restituisce un oggetto che ha una copia del nostro stato (...state) e dello stato dell'episodio che contiene il nostro payload dell'azione.
  • Nell'istruzione switch, restituiamo uno stato di default .

Si noti che i parametri di state e action nella funzione riduttore hanno rispettivamente i tipi IState e IAction . Inoltre, la funzione reducer ha un tipo di IState .

  • Infine, abbiamo dichiarato una funzione StoreProvider . Ciò consentirà a tutti i componenti della nostra app di accedere allo store.
  • Questa funzione prende children come supporto e all'interno della funzione StorePrivder , abbiamo dichiarato l'hook useReducer .
  • Abbiamo destrutturato lo state e la dispatch .
  • Per rendere il nostro negozio accessibile a tutti i componenti, abbiamo passato un valore oggetto contenente state e dispatch .

Lo state che contiene i nostri episodi e lo stato dei preferiti sarà reso accessibile da altri componenti, mentre l' dispatch è una funzione che cambia lo stato.

  • Esporteremo Store e StoreProvider , in modo che possa essere utilizzato nella nostra applicazione.

Crea Action.ts

Dovremo fare richieste all'API per recuperare gli episodi che verranno mostrati all'utente. Questo verrà fatto in un file di azione. Crea un file Action.ts , quindi incolla il codice seguente:

 import { Dispatch } from './interface/interfaces' export const fetchDataAction = async (dispatch: Dispatch) => { const URL = 'https://api.tvmaze.com/singlesearch/shows?q=la-casa-de-papel&embed=episodes' const data = await fetch(URL) const dataJSON = await data.json() return dispatch({ type: 'FETCH_DATA', payload: dataJSON.\_embedded.episodes }) }

Innanzitutto, dobbiamo importare le nostre interfacce in modo che possano essere utilizzate in questo file. Per creare l'azione sono stati eseguiti i seguenti passaggi:

  • La funzione fetchDataAction accetta i prop di dispatch come parametro.
  • Poiché la nostra funzione è asincrona, utilizzeremo async e await .
  • Creiamo una variabile( URL ) che contiene il nostro endpoint API.
  • Abbiamo un'altra variabile denominata data che contiene la risposta dall'API.
  • Quindi, memorizziamo la risposta JSON in dataJSON , dopo aver ottenuto la risposta in formato JSON chiamando data.json() .
  • Infine, restituiamo una funzione di invio che ha una proprietà di type e una stringa di FETCH_DATA . Ha anche un payload() . _embedded.episodes è l'array dell'oggetto episodi dal nostro endpoint .

Si noti che la funzione fetchDataAction recupera il nostro endpoint, lo converte in oggetti JSON e restituisce la funzione di invio, che aggiorna lo stato dichiarato in precedenza nello Store.

Il tipo di spedizione esportato è impostato su React.Dispatch . Si noti che React.Dispatch è il tipo standard per la funzione di invio in base alla base di codice @types/react , mentre <IAction> è un array dell'azione dell'interfaccia.

Componente elenco episodi

Per mantenere la riutilizzabilità della nostra app, manterremo tutti gli episodi recuperati in un file separato, quindi importeremo il file nel nostro componente homePage .

Nella cartella dei components , crea un file EpisodesList.tsx e copia e incolla il codice seguente:

 import React from 'react' import { IEpisode, IProps } from '../types/interfaces' const EpisodesList = (props: IProps): Array<JSX.Element> => { const { episodes } = props return episodes.map((episode: IEpisode) => { return ( <section key={episode.id} className='episode-box'> <img src={!!episode.image ? episode.image.medium : ''} alt={`Money Heist ${episode.name}`} /> <div>{episode.name}</div> <section style={{ display: 'flex', justifyContent: 'space-between' }}> <div> Season: {episode.season} Number: {episode.number} </div> <button type='button' > Fav </button> </section> </section> ) }) } export default EpisodesList
  • Importiamo IEpisode e IProps da interfaces.tsx .
  • Successivamente, creiamo una funzione EpisodesList che accetta oggetti di scena. Gli oggetti di scena avranno un tipo di IProps , mentre la funzione ha un tipo di Array<JSX.Element> .

Visual Studio Code suggerisce che il nostro tipo di funzione sia scritto come JSX.Element[] .

Visual Studio Code suggerisce un tipo (Anteprima grande)

Mentre Array<JSX.Element> è uguale a JSX.Element[] , Array<JSX.Element> è chiamato identità generica. Pertanto, il modello generico verrà utilizzato spesso in questo articolo.

  • All'interno della funzione destrutturiamo gli episodes da props , che ha come tipo IEpisode .

Leggi l'identità generica, questa conoscenza sarà necessaria mentre procediamo.

  • Abbiamo restituito gli oggetti di scena degli episodes e li abbiamo mappati per restituire alcuni tag HTML.
  • La prima sezione contiene la key , che è episode.id , e un className di Episode episode-box , che verrà creato in seguito. Sappiamo che i nostri episodi hanno immagini; quindi, il tag immagine.
  • L'immagine ha un operatore ternario che controlla se è presente un episode.image o un episode.image.medium . Altrimenti, visualizziamo una stringa vuota se non viene trovata alcuna immagine. Inoltre, abbiamo incluso l' episode.name in un div.

Nella section , mostriamo la stagione a cui appartiene un episodio e il suo numero. Abbiamo un pulsante con la scritta Fav . Abbiamo esportato il componente EpisodesList in modo da poterlo utilizzare nella nostra app.

Componente della pagina iniziale

Vogliamo che la home page attivi la chiamata API e visualizzi gli episodi utilizzando il componente EpisodesList che abbiamo creato. All'interno della cartella dei components , crea il componente HomePage e copia e incolla il codice seguente su di esso:

 import React, { useContext, useEffect, lazy, Suspense } from 'react' import App from '../App' import { Store } from '../Store' import { IEpisodeProps } from '../types/interfaces' import { fetchDataAction } from '../Actions' const EpisodesList = lazy<any>(() => import('./EpisodesList')) const HomePage = (): JSX.Element => { const { state, dispatch } = useContext(Store) useEffect(() => { state.episodes.length === 0 && fetchDataAction(dispatch) }) const props: IEpisodeProps = { episodes: state.episodes, store: { state, dispatch } } return ( <App> <Suspense fallback={<div>loading...</div>}> <section className='episode-layout'> <EpisodesList {...props} /> </section> </Suspense> </App> ) } export default HomePage
  • Importiamo useContext , useEffect , lazy e Suspense da React. Il componente dell'app importato è la base su cui tutti gli altri componenti devono ricevere il valore del negozio.
  • Importiamo anche Store , IEpisodeProps e FetchDataAction dai rispettivi file.
  • Importiamo il componente EpisodesList utilizzando la funzione React.lazy disponibile in React 16.6.

React lazy loading supporta la convenzione di suddivisione del codice. Pertanto, il nostro componente EpisodesList viene caricato dinamicamente, invece di essere caricato in una volta, migliorando così le prestazioni della nostra app.

  • Destrutturiamo lo state e dispatch come oggetti di scena dal Store .
  • La e commerciale (&&) useEffect controlla se lo stato degli episodi è empty (o uguale a 0). Altrimenti, restituiamo la funzione fetchDataAction .
  • Infine, restituiamo il componente App . Al suo interno, utilizziamo il wrapper Suspense e impostiamo il fallback su un div con il testo di loading . Questo verrà mostrato all'utente mentre attendiamo la risposta dall'API.
  • Il componente EpisodesList si attiverà quando i dati saranno disponibili e i dati che conterranno gli episodes sono ciò che ci diffondiamo.

Imposta Index.txs

Il componente Homepage deve essere figlio di StoreProvider . Dovremo farlo nel file di index . Rinomina index.js in index.tsx e incolla il codice seguente:

 import React from 'react' import ReactDOM from 'react-dom' import './index.css' import { StoreProvider } from './Store' import HomePage from './components/HomePage' ReactDOM.render( <StoreProvider> <HomePage /> </StoreProvider>, document.getElementById('root') )

Importiamo StoreProvider , HomePage e index.css dai rispettivi file. We wrap the HomePage component in our StoreProvider . This makes it possible for the Homepage component to access the store, as we saw in the previous section.

Abbiamo fatto molta strada. Let's check what the app looks like, without any CSS.

App without CSS (Large preview)

Create Index.css

Delete the code in the index.css file and replace it with this:

 html { font-size: 14px; } body { margin: 0; padding: 0; font-size: 10px; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } .episode-layout { display: flex; flex-wrap: wrap; min-width: 100vh; } .episode-box { padding: .5rem; } .header { display: flex; justify-content: space-between; background: white; border-bottom: 1px solid black; padding: .5rem; position: sticky; top: 0; }

Our app now has a look and feel. Here's how it looks with CSS.

(Grande anteprima)

Now we see that our episodes can finally be fetched and displayed, because we've adopted TypeScript all the way. Great, isn't it?

Add Favorite Episodes Feature

Let's add functionality that adds favorite episodes and that links it to a separate page. Let's go back to our Store component and add a few lines of code:

Note that the highlighted code is newly added:

 import React, { useReducer, createContext } from 'react' import { IState, IAction } from './types/interfaces' const initialState: IState = { episodes: [], favourites: [] } export const Store = createContext<IState | any>(initialState) const reducer = (state: IState, action: IAction): IState => { switch (action.type) { case 'FETCH_DATA': return { ...state, episodes: action.payload }
 case 'ADD_FAV': return { ...state, favourites: [...state.favourites, action.payload] }
 default: return state } } export const StoreProvider = ({ children }: JSX.ElementChildrenAttribute): JSX.Element => { const [state, dispatch] = useReducer(reducer, initialState) return <Store.Provider value={{ state, dispatch }}>{children}</Store.Provider> }

To implement the “Add favorite” feature to our app, the ADD_FAV case is added. It returns an object that holds a copy of our previous state, as well as an array with a copy of the favorite state , with the payload .

We need an action that will be called each time a user clicks on the FAV button. Let's add the highlighted code to index.tx :

 import { IAction, IEpisode, Dispatch } from './types/interfaces'
export const fetchDataAction = async (dispatch: Dispatch) => { const URL = 'https://api.tvmaze.com/singlesearch/shows?q=la-casa-de-papel&embed=episodes' const data = await fetch(URL) const dataJSON = await data.json() return dispatch({ type: 'FETCH_DATA', payload: dataJSON._embedded.episodes }) }
export const toggleFavAction = (dispatch: any, episode: IEpisode | any): IAction => { let dispatchObj = { type: 'ADD_FAV', payload: episode } return dispatch(dispatchObj) }
export const toggleFavAction = (dispatch: any, episode: IEpisode | any): IAction => { let dispatchObj = { type: 'ADD_FAV', payload: episode } return dispatch(dispatchObj) }

We create a toggleFavAction function that takes dispatch and episodes as parameters, and any and IEpisode|any as their respective types, with IAction as our function type. We have an object whose type is ADD_FAV and that has episode as its payload. Lastly, we just return and dispatch the object.

Aggiungeremo altri frammenti a EpisodeList.tsx . Copia e incolla il codice evidenziato:

 import React from 'react' import { IEpisode, IProps } from '../types/interfaces' const EpisodesList = (props: IProps): Array<JSX.Element> => {
 const { episodes, toggleFavAction, favourites, store } = props const { state, dispatch } = store

 return episodes.map((episode: IEpisode) => { return ( <section key={episode.id} className='episode-box'> <img src={!!episode.image ? episode.image.medium : ''} alt={`Money Heist - ${episode.name}`} /> <div>{episode.name}</div> <section style={{ display: 'flex', justifyContent: 'space-between' }}> <div> Seasion: {episode.season} Number: {episode.number} </div> <button type='button'
 onClick={() => toggleFavAction(state, dispatch, episode)} > {favourites.find((fav: IEpisode) => fav.id === episode.id) ? 'Unfav' : 'Fav'}
 </button> </section> </section> ) }) } export default EpisodesList

togglefavaction , favorites e store come oggetti di scena e destrutturiamo state , una dispatch dal negozio. Per selezionare il nostro episodio preferito, includiamo il metodo toggleFavAction in un evento onClick e passiamo lo state , l' dispatch e gli oggetti di scena episode come argomenti alla funzione.

Infine, esaminiamo lo stato favorite per verificare se fav.id (ID preferito) corrisponde a episode.id . In tal caso, alterniamo tra il testo Unfav e Fav . Questo aiuta l'utente a sapere se ha preferito quell'episodio o meno.

Ci stiamo avvicinando alla fine. Ma abbiamo ancora bisogno di una pagina a cui collegare gli episodi preferiti quando l'utente sceglie tra gli episodi in home page.

Se sei arrivato fin qui, datti una pacca sulla spalla.

Componente Favpage

Nella cartella dei components , crea un file FavPage.tsx . Copia e incolla il codice seguente:

 import React, { lazy, Suspense } from 'react' import App from '../App' import { Store } from '../Store' import { IEpisodeProps } from '../types/interfaces' import { toggleFavAction } from '../Actions' const EpisodesList = lazy<any>(() => import('./EpisodesList')) export default function FavPage(): JSX.Element { const { state, dispatch } = React.useContext(Store) const props: IEpisodeProps = { episodes: state.favourites, store: { state, dispatch }, toggleFavAction, favourites: state.favourites } return ( <App> <Suspense fallback={<div>loading...</div>}> <div className='episode-layout'> <EpisodesList {...props} /> </div> </Suspense> </App> ) }

Per creare la logica alla base della scelta degli episodi preferiti, abbiamo scritto un piccolo codice. Importiamo lazy e Suspense da React. Importiamo anche Store , IEpisodeProps e toggleFavAction dai rispettivi file.

Importiamo il nostro componente EpisodesList utilizzando la funzione React.lazy . Infine, restituiamo il componente App . Al suo interno, utilizziamo il wrapper Suspense e impostiamo un fallback su un div con il testo di caricamento.

Funziona in modo simile al componente Homepage . Questo componente accederà allo store per ottenere gli episodi che l'utente ha preferito. Quindi, l'elenco degli episodi viene passato al componente EpisodesList .

Aggiungiamo altri frammenti al file HomePage.tsx .

Includi toggleFavAction da ../Actions . Includere anche il metodo toggleFavAction come oggetti di scena.

 import React, { useContext, useEffect, lazy, Suspense } from 'react' import App from '../App' import { Store } from '../Store' import { IEpisodeProps } from '../types/interfaces'
import { fetchDataAction, toggleFavAction } from '../Actions'
const EpisodesList = lazy<any>(() => import('./EpisodesList')) const HomePage = (): JSX.Element => { const { state, dispatch } = useContext(Store) useEffect(() => { state.episodes.length === 0 && fetchDataAction(dispatch) }) const props: IEpisodeProps = { episodes: state.episodes, store: { state, dispatch },
 toggleFavAction, favourites: state.favourites
 } return ( <App> <Suspense fallback={<div>loading...</div>}> <section className='episode-layout'> <EpisodesList {...props} /> </section> </Suspense> </App> ) } export default HomePage

La nostra FavPage deve essere collegata, quindi abbiamo bisogno di un collegamento nella nostra intestazione in App.tsx . Per raggiungere questo obiettivo, utilizziamo Reach Router, una libreria simile a React Router. William Le spiega le differenze tra Reach Router e React Router.

Nella tua CLI, esegui npm install @reach/router @types/reach__router . Stiamo installando sia la libreria Reach Router che i tipi reach-router Reach.

Al termine dell'installazione, importa Link da @reach/router .

 import React, { useContext, Fragment } from 'react' import { Store } from './tsx'
import { Link } from '@reach/router'
 const App = ({ children }: { children: JSX.Element }): JSX.Element => {
 const { state } = useContext(Store)
return ( <Fragment> <header className='header'> <div> <h1>Money Heist</h1> <p>Pick your favourite episode</p> </div>
 <div> <Link to='/'>Home</Link> <Link to='/faves'>Favourite(s): {state.favourites.length}</Link> </div>
 </header> {children} </Fragment> ) } export default App

Destrutturiamo il negozio da useContext . Infine, la nostra casa avrà un Link e un percorso verso / , mentre la nostra preferita avrà un percorso verso /faves .

{state.favourites.length} controlla il numero di episodi negli stati preferiti e lo visualizza.

Infine, nel nostro file index.tsx , importiamo rispettivamente i componenti FavPage e HomePage e li avvolgiamo nel Router .

Copia il codice evidenziato nel codice esistente:

 import React from 'react' import ReactDOM from 'react-dom' import './index.css' import { StoreProvider } from './Store'
import { Router, RouteComponentProps } from '@reach/router' import HomePage from './components/HomePage' import FavPage from './components/FavPage' const RouterPage = ( props: { pageComponent: JSX.Element } & RouteComponentProps ) => props.pageComponent
ReactDOM.render( <StoreProvider>
 <Router> <RouterPage pageComponent={<HomePage />} path='/' /> <RouterPage pageComponent={<FavPage />} path='/faves' /> </Router>
 </StoreProvider>, document.getElementById('root') )

Ora, vediamo come funziona ADD_FAV implementato.

Il codice "Aggiungi preferito" funziona (Anteprima grande)

Rimuovi la funzionalità preferita

Infine, aggiungeremo la "funzione Rimuovi episodio", in modo che quando si fa clic sul pulsante, si alterna tra l'aggiunta o la rimozione di un episodio preferito. Visualizzeremo il numero di episodi aggiunti o rimossi nell'intestazione.

NEGOZIO

Per creare la funzionalità "Rimuovi episodio preferito", aggiungeremo un altro caso nel nostro negozio. Quindi, vai su Store.tsx e aggiungi il codice evidenziato:

 import React, { useReducer, createContext } from 'react' import { IState, IAction } from './types/interfaces' const initialState: IState = { episodes: [], favourites: [] } export const Store = createContext<IState | any>(initialState) const reducer = (state: IState, action: IAction): IState => { switch (action.type) { case 'FETCH_DATA': return { ...state, episodes: action.payload } case 'ADD_FAV': return { ...state, favourites: [...state.favourites, action.payload] }
 case 'REMOVE_FAV': return { ...state, favourites: action.payload }
 default: return state } } export const StoreProvider = ({ children }: JSX.ElementChildrenAttribute): JSX.Element => { const [state, dispatch] = useReducer(reducer, initialState) return {children} } default: return state } } export const StoreProvider = ({ children }: JSX.ElementChildrenAttribute): JSX.Element => { const [state, dispatch] = useReducer(reducer, initialState) return {children} } default: return state } } export const StoreProvider = ({ children }: JSX.ElementChildrenAttribute): JSX.Element => { const [state, dispatch] = useReducer(reducer, initialState) return {children} }

Aggiungiamo ancora un altro case chiamato REMOVE_FAV e restituiamo un oggetto contenente la copia del nostro initialState . Inoltre, lo stato dei favorites contiene il carico utile dell'azione.

AZIONE

Copia il seguente codice evidenziato e incollalo in action.ts :

 import { IAction, IEpisode, IState, Dispatch } from './types/interfaces'
export const fetchDataAction = async (dispatch: Dispatch) => { const URL = 'https://api.tvmaze.com/singlesearch/shows?q=la-casa-de-papel&embed=episodes' const data = await fetch(URL) const dataJSON = await data.json() return dispatch({ type: 'FETCH_DATA', payload: dataJSON.\_embedded.episodes }) } //Add IState withits type
export const toggleFavAction = (state: IState, dispatch: any, episode: IEpisode | any): IAction => { const episodeInFav = state.favourites.includes(episode)
 let dispatchObj = { type: 'ADD_FAV', payload: episode }
 if (episodeInFav) { const favWithoutEpisode = state.favourites.filter( (fav: IEpisode) => fav.id !== episode.id ) dispatchObj = { type: 'REMOVE_FAV', payload: favWithoutEpisode }
 } return dispatch(dispatchObj) }

Importiamo l'interfaccia IState da ./types/interfaces , perché dovremo passarla come tipo agli oggetti di state nella funzione toggleFavAction .

Viene creata una variabile episodeInFav per verificare se esiste un episodio nello stato dei favorites .

Filtramo lo stato dei preferiti per verificare se un ID preferito non è uguale a un ID episodio. Pertanto, a dispatchObj viene riassegnato un tipo di REMOVE_FAV e un payload di favWithoutEpisode .

Vediamo in anteprima il risultato della nostra app.

Conclusione

In questo articolo, abbiamo visto come impostare TypeScript in un progetto React e come migrare un progetto da vanilla React a TypeScript.

Abbiamo anche creato un'app con TypeScript e React per vedere come viene utilizzato TypeScript nei progetti React. Confido che tu sia stato in grado di imparare alcune cose.

Per favore condividi il tuo feedback e le tue esperienze con TypeScript nella sezione commenti qui sotto. Mi piacerebbe vedere cosa ti viene in mente!

Il repository di supporto per questo articolo è disponibile su GitHub.

Riferimenti

  1. "Come migrare un'app React in TypeScript", Joe Previte
  2. "Perché e come utilizzare TypeScript nella tua app React?", Mahesh Haldar