Web Paketi Kullanarak Modern React Projeleri İçin TypeScript Ayarlama

Yayınlanan: 2022-03-10
Hızlı özet ↬ Bu makale, geliştirici kodları olarak yaygın hataları tespit etmek için statik tür özelliğini sunan ve performansı artıran, dolayısıyla sağlam kurumsal uygulamalar sağlayan bir JavaScript üst simgesi olan TypeScript'i tanıtmaktadır. TypeScript, useReducer, useContext ve Reach Router gibi React kancalarını keşfederek bir Money Heist Bölüm Seçici Uygulaması oluştururken, bir React Projesinde TypeScript'i nasıl verimli bir şekilde kuracağınızı da öğreneceksiniz.

Bu yazılım geliştirme çağında, JavaScript hemen hemen her tür uygulamayı geliştirmek için kullanılabilir. Bununla birlikte, JavaScript'in dinamik olarak yazılması gerçeği, gevşek tip denetimi özelliği nedeniyle çoğu büyük kurumsal şirket için bir endişe kaynağı olabilir.

Neyse ki Ecma Teknik Komitesi 39'un JavaScript'e statik tipte bir sistem getirmesini beklemek zorunda değiliz. Bunun yerine TypeScript kullanabiliriz.

Dinamik olarak yazılan JavaScript, çalışma zamanında bu değişken somutlaştırılıncaya kadar bir değişkenin veri türünün farkında değildir. Büyük yazılım programları yazan geliştiriciler, daha önce bildirilen bir değişkeni, herhangi bir uyarı veya sorun olmaksızın farklı türde bir değere yeniden atama eğiliminde olabilir ve bu da genellikle hataların gözden kaçırılmasına neden olur.

Bu eğitimde, TypeScript'in ne olduğunu ve bir React projesinde onunla nasıl çalışılacağını öğreneceğiz. Sonunda, TypeScript ve mevcut React benzeri kancaları ( useState , useEffect , useReducer , useContext ) kullanarak Money Heist adlı TV programı için bir bölüm seçici uygulamasından oluşan bir proje oluşturmuş olacağız. Bu bilgiyle, kendi projelerinizde TypeScript ile denemeler yapabilirsiniz.

Bu makale TypeScript'e bir giriş değildir. Bu nedenle, TypeScript ve JavaScript'in temel sözdiziminden geçmeyeceğiz. Ancak, takip etmek için bu dillerden herhangi birinde uzman olmanıza gerek yok, çünkü KISS ilkesini takip etmeye çalışacağız (basit tutun, aptalca).

Atlamadan sonra daha fazlası! Aşağıdan okumaya devam edin ↓

TypeScript Nedir?

2019'da TypeScript, GitHub'da en çok kullanılan yedinci dil ve en hızlı büyüyen beşinci dil oldu. Ama TypeScript tam olarak nedir?

Resmi belgelere göre, TypeScript, düz JavaScript'i derleyen, JavaScript'in yazılı bir üst kümesidir. Microsoft ve açık kaynak topluluğu tarafından geliştirilir ve korunur.

Bu bağlamda "Süper küme", dilin JavaScript'in tüm özelliklerini ve işlevlerini ve ardından bazılarını içerdiği anlamına gelir. TypeScript, yazılı bir betik dilidir.

Geliştiricilere, tür açıklamaları, sınıfları ve arabirimi aracılığıyla kod tabanları üzerinde daha fazla kontrol sağlayarak geliştiricileri konsoldaki can sıkıcı hataları manuel olarak düzeltmek zorunda kalmaktan kurtarır.

TypeScript, JavaScript'i değiştirmek için oluşturulmadı. Bunun yerine, değerli yeni özelliklerle JavaScript'i genişletir. Düz JavaScript ile yazılmış tüm programlar, platformlar arası mobil uygulamalar ve Node.js'deki arka uçlar da dahil olmak üzere TypeScript'te beklendiği gibi çalışır.

Bu, bu eğitimde yapacağımız gibi TypeScript'te React uygulamalarını da yazabileceğiniz anlamına gelir.

Neden TypeScript?

Belki de TypeScript'in iyiliğini benimsemeye ikna olmadınız. Avantajlarından birkaçını ele alalım.

Daha Az Hata

Kodumuzdaki tüm hataları ortadan kaldıramayız, ancak onları azaltabiliriz. TypeScript, derleme zamanında türleri kontrol eder ve değişken türü değişirse hatalar atar.

Bu bariz ancak sık görülen hataları bu kadar erken bulabilmek, kodunuzu türlerle yönetmeyi çok daha kolay hale getirir.

Yeniden Düzenleme Daha Kolay

Muhtemelen çoğu zaman birçok şeyi yeniden düzenlemek istersiniz, ancak çok fazla başka koda ve diğer birçok dosyaya dokundukları için onları değiştirmekten çekinirsiniz.

TypeScript'te, bu tür şeyler, entegre geliştirme ortamınızdaki (IDE) "Sembolü yeniden adlandır" komutunun yalnızca bir tıklamasıyla genellikle yeniden düzenlenebilir.

Uygulamayı expApp olarak yeniden adlandırma (Büyük önizleme)

JavaScript gibi dinamik olarak yazılan bir dilde, aynı anda birden çok dosyayı yeniden düzenlemenin tek yolu, normal ifadeler (RegExp) kullanan geleneksel "ara ve değiştir" işlevidir.

TypeScript gibi statik olarak yazılmış bir dilde artık "ara ve değiştir" gerekli değildir. “Tüm oluşumları bul” ve “Sembolü yeniden adlandır” gibi IDE komutlarıyla, bir nesne arabiriminin verilen işlevin, sınıfın veya özelliğinin uygulamasındaki tüm oluşumları görebilirsiniz.

TypeScript, yeniden düzenlenmiş bitin tüm örneklerini bulmanıza, onu yeniden adlandırmanıza ve yeniden düzenlemeden sonra kodunuzda herhangi bir tür uyuşmazlığı olması durumunda sizi bir derleme hatasıyla uyarmanıza yardımcı olur.

TypeScript, burada ele aldıklarımızdan bile daha fazla avantaja sahiptir.

TypeScript'in Dezavantajları

TypeScript, yukarıda vurgulanan umut verici özellikler göz önüne alındığında bile, kesinlikle dezavantajlarından yoksun değildir.

Yanlış Bir Güvenlik Anlayışı

TypeScript'in tür denetimi özelliği, geliştiriciler arasında genellikle yanlış bir güvenlik duygusu yaratır. Tip kontrolü gerçekten de kodumuzda bir sorun olduğunda bizi uyarır. Ancak, statik türler genel hata yoğunluğunu azaltmaz.

Bu nedenle, türler geliştirici tarafından yazıldığından ve çalışma zamanında kontrol edilmediğinden, programınızın gücü TypeScript kullanımınıza bağlı olacaktır.

Hatalarınızı azaltmak için TypeScript arıyorsanız, lütfen bunun yerine test odaklı geliştirmeyi düşünün.

Karmaşık Yazma Sistemi

Yazma sistemi birçok açıdan harika bir araç olsa da bazen biraz karmaşık olabilir. Bu dezavantaj, JavaScript ile tamamen birlikte çalışabilir olmasından kaynaklanmaktadır ve bu da karmaşıklık için daha fazla alan bırakmaktadır.

Ancak TypeScript hala JavaScript'tir, bu nedenle JavaScript'i anlamak önemlidir.

TypeScript Ne Zaman Kullanılır?

Aşağıdaki durumlarda TypeScript kullanmanızı tavsiye ederim:

  • Uzun bir süre boyunca bakımı yapılacak bir uygulama oluşturmak istiyorsanız, TypeScript ile başlamanızı şiddetle tavsiye ederim, çünkü bu kendi kendini belgeleyen kodu destekler, böylece diğer geliştiricilerin kod tabanınıza katıldıklarında kodunuzu kolayca anlamalarına yardımcı olur. .
  • Bir kitaplık oluşturmanız gerekiyorsa, onu TypeScript'te yazmayı düşünün. Kitaplığınızı kullanan geliştiricilere uygun türleri önermek için kod düzenleyicilerine yardımcı olacaktır.

Son birkaç bölümde TypeScript'in artılarını ve eksilerini dengeledik. Şimdi günün işine geçelim: Modern bir React projesinde TypeScript kurulumu .

Başlarken

Bir React Projesinde TypeScript kurmanın birkaç yolu vardır. Bu eğitimde, sadece ikisini ele alacağız.

Yöntem 1: React Uygulaması + TypeScript Oluştur

Yaklaşık iki yıl önce, React ekibi TypeScript desteğiyle Create React App 2.1'i yayınladı. Bu nedenle, TypeScript'i projenize dahil etmek için hiçbir zaman ağır işler yapmanız gerekmeyebilir.

Create React Uygulamasında TypeScript Duyurusu (Geniş önizleme)

Yeni bir React Uygulaması Oluştur projesi başlatmak için bunu çalıştırabilirsiniz…

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

… veya bu:

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

TypeScript'i Create React App projesine eklemek için önce onu ve ilgili @types :

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

… veya:

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

Ardından dosyaları yeniden adlandırın (örneğin, index.js için index.tsx ) ve geliştirme sunucunuzu yeniden başlatın !

Bu hızlıydı, değil mi?

Yöntem 2: TypeScript'i Web Paketiyle Kurma

Webpack, JavaScript uygulamaları için statik bir modül paketleyicidir. Uygulamanızdan tüm kodu alır ve bir web tarayıcısında kullanılabilir hale getirir. Modüller, web sitenizde kolayca kullanılmak üzere paketlenmiş, uygulamanızın JavaScript, node_modules , resimler ve CSS stillerinden oluşturulmuş yeniden kullanılabilir kod parçalarıdır.

Yeni Proje Oluştur

Projemiz için yeni bir dizin oluşturarak başlayalım:

 mkdir react-webpack cd react-webpack

Projemizi başlatmak için npm kullanacağız:

 npm init -y

Yukarıdaki komut, bazı varsayılan değerlere sahip bir package.json dosyası oluşturacaktır. Ayrıca web paketi, TypeScript ve bazı React'e özgü modüller için bazı bağımlılıklar ekleyelim.

Paketleri Yükleme

Son olarak, gerekli paketleri kurmamız gerekecek. Komut satırı arabiriminizi (CLI) açın ve şunu çalıştırın:

 #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

Ayrıca react-webpack klasörümüzün altına manuel olarak birkaç farklı dosya ve klasör ekleyelim:

  1. Web paketiyle ilgili yapılandırmaları eklemek için webpack.config.js ekleyin.
  2. Tüm TypeScript yapılandırmalarımız için tsconfig.json ekleyin.
  3. Yeni bir dizin ekleyin, src .
  4. src klasöründe yeni bir dizin oluşturun, components .
  5. Son olarak, components klasörüne index.html , App.tsx ve index.tsx ekleyin.

Proje Yapısı

Böylece klasör yapımız şöyle görünecek:

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

Bazı Kodları Eklemeye Başlayın

index.html ile başlayacağız:

 <!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>

Bu, output kimliğine sahip boş bir div ile HTML'yi oluşturacaktır.

Kodu React bileşenimiz 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> );

Bir arayüz nesnesi yarattık ve buna HelloWorldProps adını verdik, userName ve lang bir string tipine sahip.

props öğelerini App bileşenimize aktardık ve dışa aktardık.

Şimdi index.tsx içindeki kodu güncelleyelim:

 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") );

App bileşenini index.tsx . Web paketi, .ts veya .tsx uzantılı herhangi bir dosya gördüğünde, bu dosyayı harika-typescript-loader kitaplığını kullanarak aktaracaktır.

TypeScript Yapılandırması

Ardından tsconfig.json bazı yapılandırmalar ekleyeceğiz:

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

Ayrıca tsconfig.json eklediğimiz farklı seçeneklere de bakalım:

  • compilerOptions Farklı derleyici seçeneklerini temsil eder.
  • jsx:react .tsx dosyalarına JSX desteği ekler.
  • lib Derlemeye kitaplık dosyalarının bir listesini ekler (örneğin, es2015 kullanmak ECMAScript 6 sözdizimini kullanmamıza izin verir).
  • module Modül kodu üretir.
  • noImplicitAny any tür ima edilen bildirimler için hataları artırır.
  • outDir Çıkış dizinini temsil eder.
  • sourceMap Uygulamada hata ayıklamak için çok yararlı olabilecek bir .map dosyası oluşturur.
  • target Kodumuzun aktarılacağı hedef ECMAScript sürümünü temsil eder (belirli tarayıcı gereksinimlerimize göre bir sürüm ekleyebiliriz).
  • include Eklenecek dosya listesini belirtmek için kullanılır.

Web Paketi Yapılandırması

webpack.config.js dosyasına biraz web paketi yapılandırması ekleyelim.

 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", }), ], };

webpack.config.js eklediğimiz farklı seçeneklere bakalım:

  • entry Bu, uygulamamız için giriş noktasını belirtir. Derlememize dahil etmek istediğimiz tek bir dosya veya bir dizi dosya olabilir.
  • output Bu, çıktı yapılandırmasını içerir. Uygulama, projemizden diske paketlenmiş kod çıktısı almaya çalışırken buna bakar. Yol, çıktısı alınacak kodun çıktı dizinini temsil eder ve dosya adı, aynısı için dosya adını temsil eder. Genellikle bundle.js olarak adlandırılır.
  • resolve Webpack, dosyayı gruplamak veya atlamak arasında karar vermek için bu özniteliğe bakar. Bu nedenle, projemizde web paketi, demetleme için .js , .jsx , .json , .ts ve .tsx uzantılı dosyaları dikkate alacaktır.
  • module Web paketinin, uygulama tarafından istendiğinde, yükleyicileri kullanarak belirli bir dosyayı yüklemesini sağlayabiliriz. Aşağıdakileri belirten bir kural nesnesi alır:
    • .tsx veya .ts uzantısıyla biten herhangi bir dosya, yüklenmek için awesome-typescript-loader kullanmalıdır;
    • .js uzantısıyla biten dosyalar source-map-loader ile yüklenmelidir;
    • .css uzantısıyla biten dosyalar css-loader ile yüklenmelidir.
  • plugins Web paketinin kendi sınırlamaları vardır ve bunların üstesinden gelmek ve yeteneklerini genişletmek için eklentiler sağlar. Örneğin, html-webpack-plugin , ./src/component/index.html dizinindeki index.html dosyasından tarayıcıya işlenen bir şablon dosyası oluşturur.

MiniCssExtractPlugin , uygulamanın üst CSS dosyasını işler.

package.json'a Script Ekleme

package.json dosyamıza React uygulamaları oluşturmak için farklı komut dosyaları ekleyebiliriz:

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

Şimdi, npm start . Her şey yolunda gittiyse, şunu görmelisiniz:

React-Webpack kurulum çıktısı (Büyük önizleme)

Web paketi konusunda bilginiz varsa, bu kurulum için depoyu klonlayın ve projelerinizde kullanın.

Dosya Oluşturma

Bir src klasörü ve bir index.tsx dosyası oluşturun. Bu, React'i oluşturan temel dosya olacaktır.

Şimdi, npm start , sunucumuzu çalıştıracak ve yeni bir sekme açacaktır. npm run build , üretim için web paketi oluşturacak ve bizim için bir derleme klasörü oluşturacaktır.

Create React App ve web paketi yapılandırma yöntemini kullanarak TypeScript'i sıfırdan nasıl kuracağımızı gördük.

TypeScript'i tam olarak kavramanın en hızlı yollarından biri, mevcut Vanilla React projelerinizden birini TypeScript'e dönüştürmektir. Ne yazık ki, TypeScript'i mevcut bir Vanilla React projesinde aşamalı olarak benimsemek streslidir, çünkü tüm dosyaları çıkarmayı veya yeniden adlandırmayı gerektirir, bu da proje büyük bir ekibe aitse çakışmalara ve devasa bir çekme talebine neden olur.

Ardından, bir React projesinin TypeScript'e nasıl kolayca taşınacağına bakacağız.

Mevcut Bir Create React Uygulamasını TypeScript'e Taşıyın

Bu süreci daha yönetilebilir hale getirmek için, bireysel parçalar halinde geçiş yapmamızı sağlayacak adımlara böleceğiz. Projemizi taşımak için atacağımız adımlar şunlardır:

  1. TypeScript ve türleri ekleyin.
  2. tsconfig.json ekleyin.
  3. Küçük başla.
  4. Dosya uzantısını .tsx olarak yeniden adlandırın.

1. TypeScript'i Projeye Ekleyin

Öncelikle projemize TypeScript eklememiz gerekecek. React projenizin Create React App ile başlatıldığını varsayarsak, aşağıdakileri çalıştırabiliriz:

 # 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

Henüz hiçbir şeyi TypeScript olarak değiştirmediğimize dikkat edin. Projeyi yerel olarak başlatmak için komutu çalıştırırsak ( npm start veya thread yarn start ), hiçbir şey değişmez. Eğer durum buysa, o zaman harika! Bir sonraki adım için hazırız.

2. tsconfig.json Dosyasını ekleyin

TypeScript'ten yararlanmadan önce, onu tsconfig.json dosyası aracılığıyla yapılandırmamız gerekiyor. Başlamanın en basit yolu, bu komutu kullanarak bir iskele kurmaktır:

 npx tsc --init

Bu bize birçok yorumlanmış kodla birlikte bazı temel bilgileri verir. Şimdi, tsconfig.json tüm kodu şununla değiştirin:

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

TypeScript Yapılandırması

Ayrıca tsconfig.json eklediğimiz farklı seçeneklere de bakalım:

  • compilerOptions Farklı derleyici seçeneklerini temsil eder.
    • target Daha yeni JavaScript yapılarını ECMAScript 5 gibi daha eski bir sürüme çevirir.
    • lib Derlemeye kitaplık dosyalarının bir listesini ekler (örneğin, es2015 kullanmak ECMAScript 6 sözdizimini kullanmamıza izin verir).
    • jsx:react .tsx dosyalarına JSX desteği ekler.
    • lib Derlemeye kitaplık dosyalarının bir listesini ekler (örneğin, es2015 kullanmak ECMAScript 6 sözdizimini kullanmamıza izin verir).
    • module Modül kodu üretir.
    • noImplicitAny any tür ima edilen bildirimler için hata oluşturmak için kullanılır.
    • outDir Çıkış dizinini temsil eder.
    • sourceMap Uygulamamızda hata ayıklamak için çok yararlı olabilecek bir .map dosyası oluşturur.
    • include Eklenecek dosya listesini belirtmek için kullanılır.

Konfigürasyon seçenekleri, bir projenin talebine göre değişiklik gösterecektir. Projenize neyin uyacağını bulmak için TypeScript seçenekleri elektronik tablosunu kontrol etmeniz gerekebilir.

Sadece işleri hazır hale getirmek için gerekli önlemleri aldık. Sonraki adımımız bir dosyayı TypeScript'e geçirmek.

3. Basit Bir Bileşenle Başlayın

TypeScript'in kademeli olarak benimsenme yeteneğinden yararlanın. Kendi hızınızda bir seferde bir dosya gidin. Kendiniz ve ekibiniz için mantıklı olanı yapın. Hepsini bir anda halletmeye çalışmayın.

Bunu düzgün bir şekilde dönüştürmek için iki şey yapmamız gerekiyor:

  1. Dosya uzantısını .tsx olarak değiştirin.
  2. Tür ek açıklamasını ekleyin (bu, biraz TypeScript bilgisi gerektirir).

4. Dosya Uzantılarını .tsx olarak yeniden adlandırın

Geniş bir kod tabanında, dosyaları tek tek yeniden adlandırmak yorucu görünebilir.

macOS'ta birden çok dosyayı yeniden adlandırın

Birden çok dosyayı yeniden adlandırmak zaman kaybı olabilir. Mac'te nasıl yapabileceğiniz aşağıda açıklanmıştır. Yeniden adlandırmak istediğiniz dosyaları içeren klasöre sağ tıklayın (veya Ctrl + tıklayın veya bir MacBook kullanıyorsanız izleme dörtgeninde iki parmağınızla aynı anda tıklayın). Ardından, “Finder'da Göster” seçeneğini tıklayın. Finder'da yeniden adlandırmak istediğiniz tüm dosyaları seçin. Seçili dosyalara sağ tıklayın ve “X öğelerini yeniden adlandır…” seçeneğini seçin. Ardından, şöyle bir şey göreceksiniz:

Mac'te dosyaları yeniden adlandırın (Büyük önizleme)

Bulmak istediğiniz dizeyi ve bulunan dizeyi değiştirmek istediğiniz dizeyi girin ve "Yeniden Adlandır" düğmesine basın. Tamamlandı.

Windows'ta birden çok dosyayı yeniden adlandırın

Windows'ta birden çok dosyayı yeniden adlandırmak bu öğreticinin kapsamı dışındadır, ancak eksiksiz bir kılavuz mevcuttur. Dosyaları yeniden adlandırdıktan sonra genellikle hata alırsınız; tür açıklamalarını eklemeniz yeterlidir. Bunu belgelerde tazeleyebilirsiniz.

Bir React uygulamasında TypeScript'in nasıl kurulacağını ele aldık. Şimdi, TypeScript kullanarak Money Heist için bir bölüm seçici uygulaması oluşturalım.

Temel TypeScript türlerini ele almayacağız. Bu öğreticiye devam etmeden önce belgeleri gözden geçirmek gerekir.

İnşa Zamanı

Bu süreci daha az yıldırıcı hissettirmek için, uygulamayı ayrı parçalar halinde oluşturmamızı sağlayacak adımlara böleceğiz. Money Heist bölüm seçicisini oluşturmak için atacağımız adımların tümü:

  • Bir Create React Uygulaması Oluşturun.
  • Bölümleri getir.
    • interface.ts içinde bölümlerimiz için uygun türleri ve interface.ts oluşturun.
    • store.tsx bölümleri almak için mağazayı ayarlayın.
    • action.ts bölümleri almak için eylemi oluşturun.
    • Alınan bölümleri tutan bir EpisodeList.tsx bileşeni oluşturun.
    • React Lazy and Suspense kullanarak EpisodesList bileşenini ana sayfamıza aktarın.
  • Bölüm ekleyin.
    • store.tsx bölümleri eklemek için mağazayı ayarlayın.
    • action.ts bölüm eklemek için eylemi oluşturun.
  • Bölümleri kaldırın.
    • store.tsx bölümleri silmek için mağazayı ayarlayın.
    • action.ts bölümleri silmek için eylemi oluşturun.
  • Favori bölüm.
    • Favori bölümdeki EpisodesList bileşenini içe aktarın.
    • Favori bölümün içindeki EpisodesList Oluşturun.
  • Navigasyon için Reach Router'ı kullanma.

React'i Ayarla

React'i kurmanın en kolay yolu Create React App kullanmaktır. Create React App, tek sayfalık React uygulamaları oluşturmanın resmi olarak desteklenen bir yoludur. Konfigürasyon gerektirmeyen modern bir yapı kurulumu sunar.

Oluşturacağımız uygulamayı önyüklemek için kullanacağız. CLI'nizden aşağıdaki komutu çalıştırın:

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

Kurulum başarılı olduktan sonra, npm start çalıştırarak React sunucusunu başlatın.

React başlangıç ​​sayfası (Büyük önizleme)

TypeScript'te Arayüzleri ve Türleri Anlama

TypeScript'teki arabirimler, nesne özelliklerine tür vermemiz gerektiğinde kullanılır. Bu nedenle, türlerimizi tanımlamak için arayüzler kullanıyor olacağız.

 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 }

Yukarıdaki kodu derlerken şu hatayı görürüz: “Mülkiyet salary türleri uyumsuz. Tür string , number yazmak için atanamaz."

TypeScript'te bu tür hatalar, bir özelliğe veya değişkene tanımlanan türden başka bir tür atandığında meydana gelir. Spesifik olarak, yukarıdaki pasaj, salary özelliğine number türü yerine bir string türü atandığı anlamına gelir.

src klasörümüzde interface.ts dosyasını oluşturalım. Bu kodu kopyalayıp içine yapıştırın:

 /** |-------------------------------------------------- | 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> }

Arayüz adına bir “I” eklemek iyi bir uygulamadır. Kodu okunabilir hale getirir. Ancak, hariç tutmaya karar verebilirsiniz.

Bölüm Arayüzü

API'miz, airdate , airstamp , airtime , id , image , name , number , runtime , season , summary ve url gibi bir dizi özellik döndürür. Bu nedenle, bir IEpisode arabirimi tanımladık ve uygun veri türlerini nesne özelliklerine ayarladık.

IState Arayüzü

IState arayüzümüz, sırasıyla episodes ve favorites kullanılanlar özelliklerine ve bir Array<IEpisode> arayüzüne sahiptir.

IAeylem

IAction arabirimi özellikleri, payload ve type . type özelliği bir dize türüne sahipken, yükün bir Array | any Array | any .

Array | any Array | any , bölüm arabiriminin bir dizisi veya herhangi bir tür anlamına gelir.

Dispatch türü, React.Dispatch ve bir <IAction> arabirimi olarak ayarlanmıştır. @types/react kod tabanına göre React.Dispatch dispatch işlevi için standart tür olduğunu, <IAction> ise Arayüz eyleminin bir dizisi olduğunu unutmayın.

Ayrıca, Visual Studio Code'da TypeScript denetleyicisi bulunur. Bu nedenle, yalnızca kodu vurgulayarak veya üzerine gelerek uygun türü önermek için yeterince akıllıdır.

Başka bir deyişle, uygulamalarımız genelinde arayüzümüzü kullanabilmemiz için onu dışa aktarmamız gerekiyor. Şimdiye kadar, nesnemizin türünü tutan mağazamız ve arayüzlerimiz var. Şimdi mağazamızı oluşturalım. Diğer arabirimlerin açıklananlarla aynı kuralları izlediğine dikkat edin.

Bölümleri Getir

Mağaza Oluşturma

Bölümlerimizi getirmek için, verilerin ilk durumunu tutan ve redüktör işlevimizi tanımlayan bir depoya ihtiyacımız var.

Bunu ayarlamak için useReducer kancasını kullanacağız. src klasörünüzde bir store.tsx dosyası oluşturun. Aşağıdaki kodu kopyalayıp içine yapıştırın.

 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} }

Mağazayı oluşturmak için attığımız adımlar şunlardır:

  • Mağazamızı tanımlarken, useReducer kancasına ve createContext API'sine ihtiyacımız var, bu yüzden onu içe aktardık.
  • IState ve IAction ./types/interfaces .
  • IState türünde bir initialState nesnesi ve her ikisi de sırasıyla boş bir diziye ayarlanmış bölümlerin ve sık kullanılanların özelliklerini IState .
  • Ardından, createContext yöntemini tutan ve initialState geçirilen bir Store değişkeni oluşturduk.

createContext yöntem türü <IState | any> <IState | any> , bu, bir tür <IState> veya any biri olabileceği anlamına gelir. Bu makalede sıklıkla kullanılan any türü göreceğiz.

  • Ardından, bir reducer işlevi bildirdik ve state ve action parametre olarak ilettik. reducer işlevi, action.type değerini kontrol eden bir switch ifadesine sahiptir. Değer FETCH_DATA ise, durumumuzun (...state) ve eylem yükümüzü tutan bölüm durumunun bir kopyasına sahip bir nesne döndürür.
  • switch ifadesinde bir default durumu döndürürüz.

Redüktör işlevindeki state ve action parametrelerinin sırasıyla IState ve IAction türleri olduğunu unutmayın. Ayrıca, reducer işlevi bir tür IState .

  • Son olarak, bir StoreProvider işlevi bildirdik. Bu, uygulamamızdaki tüm bileşenlerin mağazaya erişmesini sağlayacaktır.
  • Bu işlev children bir destek olarak alır ve StorePrivder işlevinin içinde useReducer kancasını bildirdik.
  • state ve dispatch .
  • Mağazamızı tüm bileşenler için erişilebilir kılmak için, state ve dispatch içeren bir nesne değeri ilettik.

Bölümlerimizi ve favori state içeren durum, diğer bileşenler tarafından erişilebilir hale getirilirken, dispatch durumu değiştiren bir işlevdir.

  • Uygulamamızda kullanılabilmesi için Store ve StoreProvider dışa aktaracağız.

Action.ts oluştur

Kullanıcıya gösterilecek bölümleri almak için API'ye isteklerde bulunmamız gerekecek. Bu bir eylem dosyasında yapılacaktır. Bir Action.ts dosyası oluşturun ve ardından aşağıdaki kodu yapıştırın:

 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 }) }

Öncelikle, bu dosyada kullanılabilmesi için arayüzlerimizi içe aktarmamız gerekiyor. Eylemi oluşturmak için aşağıdaki adımlar atılmıştır:

  • fetchDataAction işlevi, bir parametre olarak dispatch malzemeleri alır.
  • İşlevimiz eşzamansız olduğundan, async ve await olacağız.
  • API uç noktamızı tutan bir değişken ( URL ) oluşturuyoruz.
  • API'den gelen yanıtı tutan data adında başka bir değişkenimiz var.
  • Daha sonra, data.json() çağırarak JSON formatında cevabı aldıktan sonra, JSON cevabını dataJSON içinde saklarız.
  • Son olarak, type özelliğine ve FETCH_DATA dizesine sahip bir gönderme işlevi döndürürüz. Ayrıca bir payload() vardır. _embedded.episodes , endpoint noktamızdaki bölümler nesnesinin dizisidir.

fetchDataAction işlevinin uç noktamızı aldığını, onu JSON nesnelerine dönüştürdüğünü ve Store'da daha önce bildirilen durumu güncelleyen gönderme işlevini döndürdüğünü unutmayın.

Dışa aktarılan gönderim türü React.Dispatch olarak ayarlanmıştır. React.Dispatch @types/react kod tabanına göre gönderme işlevi için standart tür olduğunu, <IAction> ise Arayüz Eyleminin bir dizisi olduğunu unutmayın.

Bölüm Listesi Bileşeni

Uygulamamızın yeniden kullanılabilirliğini korumak için, alınan tüm bölümleri ayrı bir dosyada tutacağız ve ardından dosyayı ana sayfa bileşenimize homePage .

components klasöründe bir EpisodesList.tsx dosyası oluşturun ve aşağıdaki kodu kopyalayıp ona yapıştırın:

 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
  • IEpisode ve IProps interfaces.tsx dosyasından içe aktarıyoruz.
  • Ardından, sahne alan bir EpisodesList işlevi oluşturuyoruz. Props, bir tür IProps sahipken, işlevin bir Array<JSX.Element> türü vardır.

Visual Studio Code, işlev JSX.Element[] olarak yazılmasını önerir.

Visual Studio Code bir tür önerir (Büyük önizleme)

Array<JSX.Element> , JSX.Element[] eşit olsa da, Array<JSX.Element> genel kimlik olarak adlandırılır. Bu nedenle, genel kalıp bu makalede sıklıkla kullanılacaktır.

  • İşlevin içinde, tür olarak IEpisode sahip olan props öğesinden episodes yok ederiz.

Genel kimlik hakkında bilgi edinin, Devam ederken bu bilgiye ihtiyaç duyulacaktır.

  • Birkaç HTML etiketi döndürmek için episodes aksesuarlarını döndürdük ve bunların haritasını çıkardık.
  • İlk bölüm, episode.id olan key ve daha sonra oluşturulacak olan partition episode-box className içerir. Bölümlerimizin görüntüleri olduğunu biliyoruz; bu nedenle, resim etiketi.
  • Görüntünün, bir episode.image veya bir episode.image.medium olup olmadığını kontrol eden bir üçlü operatörü vardır. Aksi takdirde, resim bulunamazsa boş bir dize görüntüleriz. Ayrıca, bölüm adını bir episode.name ekledik.

section , bir bölümün ait olduğu sezonu ve numarasını gösteriyoruz. Fav metnine sahip bir düğmemiz var. Uygulamamızda kullanabilmemiz için EpisodesList bileşenini dışa aktardık.

Ana Sayfa Bileşeni

Ana sayfanın API çağrısını tetiklemesini ve oluşturduğumuz EpisodesList bileşenini kullanarak bölümleri görüntülemesini istiyoruz. components klasörünün içinde HomePage bileşenini oluşturun ve aşağıdaki kodu kopyalayıp ona yapıştırın:

 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
  • useContext , useEffect , lazy ve Suspense öğelerini içe aktarıyoruz. İçe aktarılan uygulama bileşeni, diğer tüm bileşenlerin mağazanın değerini alması gereken temeldir.
  • Ayrıca Store , IEpisodeProps ve FetchDataAction ilgili dosyalarından içe aktarırız.
  • React 16.6'da bulunan React.lazy özelliğini kullanarak EpisodesList bileşenini içe aktarıyoruz.

React tembel yükleme, kod bölme kuralını destekler. Böylece, EpisodesList bileşenimiz bir kerede yüklenmek yerine dinamik olarak yüklenir, böylece uygulamamızın performansı iyileştirilir.

  • Durumu state ve Store sahne olarak dispatch .
  • useEffect kancasındaki ve işareti (&&), bölüm durumumuzun empty (veya 0'a eşit) olup olmadığını kontrol eder. Aksi takdirde, fetchDataAction işlevini döndürürüz.
  • Son olarak, App bileşenini iade ediyoruz. İçinde, Suspense sarmalayıcısını kullanıyoruz ve loading metniyle birlikte bir div'e fallback ayarlıyoruz. API'den yanıt beklerken bu kullanıcıya gösterilecektir.
  • EpisodesList bileşeni, veriler mevcut olduğunda eklenecektir ve episodes içerecek olan veriler, ona yaydığımız şeydir.

Index.txs Kurulumu

Ana Homepage bileşeninin StoreProvider alt öğesi olması gerekir. Bunu index dosyasında yapmamız gerekecek. index.js index.tsx olarak yeniden adlandırın ve aşağıdaki kodu yapıştırın:

 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') )

StoreProvider , HomePage ve index.css dosyalarını ilgili dosyalarından içe aktarıyoruz. 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.

Uzun yoldan geldik. 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.

(Büyük önizleme)

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.

EpisodeList.tsx biraz daha snippet ekleyeceğiz. Vurgulanan kodu kopyalayıp yapıştırın:

 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

Sahne olarak togglefavaction , favorites ve store dahil ediyoruz ve mağazadan bir dispatch olan state 'i yok ediyoruz. Favori bölümümüzü seçmek için toggleFavAction yöntemini bir onClick olayına dahil ediyoruz ve state , dispatch ve episode özelliklerini işleve argüman olarak iletiyoruz.

Son olarak, fav.id (favori kimlik) episode.id ile eşleşip eşleşmediğini kontrol etmek için favorite durum arasında dolaşıyoruz. Varsa, Unfav ve Fav metni arasında geçiş yaparız. Bu, kullanıcının o bölümü favorilerine alıp almadığını bilmesine yardımcı olur.

Sona yaklaşıyoruz. Ancak yine de, kullanıcı ana sayfadaki bölümler arasından seçim yaptığında favori bölümlerin bağlanabileceği bir sayfaya ihtiyacımız var.

Buraya kadar geldiyseniz, sırtınızı sıvazlayın.

Favori Sayfası Bileşeni

components klasöründe bir FavPage.tsx dosyası oluşturun. Aşağıdaki kodu kopyalayıp ona yapıştırın:

 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> ) }

Favori bölümleri seçmenin ardındaki mantığı oluşturmak için küçük bir kod yazdık. lazy ve Suspense içe aktarıyoruz. Ayrıca Store , IEpisodeProps ve toggleFavAction ilgili dosyalarından içe aktarırız.

React.lazy özelliğini kullanarak EpisodesList bileşenimizi içe aktarıyoruz. Son olarak, App bileşenini iade ediyoruz. İçinde, Suspense sarmalayıcısını kullanıyoruz ve yükleme metniyle bir div'e geri dönüş ayarlıyoruz.

Bu, Homepage bileşenine benzer şekilde çalışır. Bu bileşen, kullanıcının favorilerine eklemiş olduğu bölümleri almak için mağazaya erişecektir. Ardından, bölümlerin listesi, EpisodesList bileşenine geçirilir.

HomePage.tsx dosyasına birkaç snippet daha ekleyelim.

../Actions toggleFavAction ekleyin. Ayrıca toggleFavAction yöntemini sahne malzemesi olarak dahil edin.

 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

FavPage bağlantılı olması gerekiyor, bu yüzden App.tsx içindeki başlığımızda bir bağlantıya ihtiyacımız var. Bunu başarmak için React Router'a benzer bir kütüphane olan Reach Router'ı kullanıyoruz. William Le, Reach Router ve React Router arasındaki farkları açıklıyor.

npm install @reach/router @types/reach__router . Hem Reach Router kitaplığını hem de access reach-router türlerini kuruyoruz.

Başarılı kurulumdan sonra Link @reach/router içe aktarın.

 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

useContext yok ediyoruz. Son olarak, evimizin bir Link ve / için bir yolu olacak, favorimizin /faves için bir yolu var.

{state.favourites.length} , favori durumlarındaki bölüm sayısını kontrol eder ve görüntüler.

Son olarak index.tsx dosyamızda sırasıyla FavPage ve HomePage bileşenlerini import edip Router içerisine sarıyoruz.

Vurgulanan kodu mevcut koda kopyalayın:

 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') )

Şimdi, uygulanan ADD_FAV nasıl çalıştığını görelim.

"Favori ekle" kodu çalışıyor (Büyük önizleme)

Favori İşlevselliği Kaldır

Son olarak, “Bölüm kaldır özelliğini” ekleyeceğiz, böylece butona tıklandığında favori bölüm ekleme veya çıkarma arasında geçiş yapıyoruz. Başlıkta eklenen veya kaldırılan bölümlerin sayısını görüntüleyeceğiz.

MAĞAZA

"Favori bölümü kaldır" işlevini oluşturmak için mağazamıza başka bir vaka ekleyeceğiz. Bu nedenle Store.tsx gidin ve vurgulanan kodu ekleyin:

 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} }

REMOVE_FAV adında başka bir durum daha ekleriz ve initialState kopyasını içeren bir nesne döndürürüz. Ayrıca, favorites durumu, eylem yükünü içerir.

EYLEM

Aşağıdaki vurgulanan kodu kopyalayın ve action.ts yapıştırın:

 { import { IAction, IEpisode, IState, Dispatch } from './types/interfaces' içe aktarın
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) }

IState arabirimini ./types/interfaces öğesinden içe aktarıyoruz, çünkü onu tür olarak toggleFavAction işlevinde state desteğine aktarmamız gerekecek.

favorites durumunda bulunan bir bölüm olup olmadığını kontrol etmek için bir episodeInFav değişkeni oluşturulur.

Favori kimliğinin bölüm kimliğine eşit olup olmadığını kontrol etmek için favori durumunu filtreleriz. Böylece, dispatchObj bir REMOVE_FAV türü ve bir favWithoutEpisode yükü yeniden atanır.

Uygulamamızın sonucunu önizleyelim.

Çözüm

Bu yazıda, bir React projesinde TypeScript'in nasıl kurulacağını ve bir projenin Vanilla React'ten TypeScript'e nasıl taşınacağını gördük.

Ayrıca TypeScript'in React projelerinde nasıl kullanıldığını görmek için TypeScript ve React ile bir uygulama geliştirdik. Birkaç şey öğrenebildiğine inanıyorum.

Lütfen geri bildirimlerinizi ve deneyimlerinizi TypeScript ile aşağıdaki yorumlar bölümünde paylaşın. Ne bulduğunu görmek isterim!

Bu makalenin destekleyici deposu GitHub'da mevcuttur.

Referanslar

  1. "Bir React Uygulamasını TypeScript'e Nasıl Geçiririm?" Joe Previte
  2. “React Uygulamanızda TypeScript Neden ve Nasıl Kullanılır?” Mahesh Haldar