by Kelvin Mai
通過凱文麥
我如何使用React和Typescript在freeCodeCamp中構建天氣應用 (How I built the weather app in freeCodeCamp using React and Typescript)
So I finally decided to come back to freeCodeCamp and try to finish out my Front End Development Certificate. I had already finished all the algorithms and tutorials earlier last year, and the only thing missing was the projects.
因此,我最終決定返回freeCodeCamp并嘗試完成我的前端開發證書。 去年早些時候,我已經完成了所有算法和教程,唯一缺少的是項目。
But now that I have more experience as a Full Stack Developer, most of the projects are a bit easy for my current level. So I had two choices. I could either go back to the basics and finish them all in a day, or I could kill two birds with one stone: have some fun and experiment with technology while working on these projects. I opted for the latter.
但是,既然我有更多的全棧開發人員經驗,就我目前的水平而言,大多數項目都比較容易。 所以我有兩個選擇。 我或者可以回到基礎上并在一天內完成所有步驟,或者可以用一塊石頭殺死兩只鳥:在進行這些項目時,可以玩得開心,可以嘗試技術。 我選擇了后者。
But let’s make that three birds — because I have been wanting to write a tutorial/guide thing for a while. Today, what we’re going to tackle is the Show The Local Weather project. But this time, it’s going to combine React and Typescript! You can take a look at the finished code in this GitHub repo, as well as a live demo here.
但是讓我們把這三只鳥做成一只鳥-因為我一直想寫一篇教程/指南的東西。 今天,我們要解決的是“ 顯示當地天氣”項目。 但是這次,它將結合React和Typescript! 您可以在此GitHub存儲庫中查看完成的代碼,以及此處的實時演示。
背景 (Background)
So first thing’s first: why would I want to do this? Well here’s the thing: I have been jumping back and forth with Angular 5 and React for a while now. And I like React more as a framework. It’s small and concise, but has all the features you need to create a fully functional Single Page Application. As for Angular, it is far too large for me to enjoy for an app as small as this…but it uses Typescript!
首先是第一件事:我為什么要這樣做? 好了:我一直在使用Angular 5和React來回跳躍了一段時間。 我更喜歡React作為框架。 它雖然小巧簡潔,但具有創建完整功能的單頁應用程序所需的所有功能。 至于Angular,對于像這樣小的應用程序來說,它太大了,我無法欣賞……但是它使用Typescript!
TypeScript is a super set of JavaScript that adds a lot of features that are just missing from JavaScript, even with the enhancements from ES6/7. It’s mostly known for it’s static typing. So I wondered if I could get the best of both worlds. The answer was a resounding YES!… Redux not included. (I mean you can include Redux, but so far it’s been a pain to set up, so I won’t be doing it for this guide.)
TypeScript是JavaScript的超集,即使添加了ES6 / 7的增強功能,它也添加了JavaScript所缺少的許多功能。 它以靜態類型而聞名。 所以我想知道我能否同時兼顧兩者。 答案是肯定的!!不包括Redux。 (我的意思是您可以包括Redux,但到目前為止,設置起來很麻煩,因此在本指南中我不會這樣做。)
For this project, we’re going to focus on the bare minimum of the User Stories, because my focus is the technology rather than any extra features. As such, the API we’ll be using for this app is going to be Wunderround. It’s perfect for what we’re building, because they offer temperatures in both Fahrenheit and Celsius and also provide icons for the different weather conditions. This means less programmatic work on our end.
對于本項目,我們將只關注最少的用戶故事,因為我的重點是技術而不是任何其他功能。 因此,我們將為此應用程序使用的API是Wunderround 。 對于我們正在建造的建筑物來說,它是完美的選擇,因為它們既提供華氏溫度,又提供攝氏溫度,并且還提供針對不同天氣情況的圖標。 這意味著我們這方面的編程工作會減少。
步驟0:設定 (Step 0: Set Up)
I’ll be using create-react-app
for this project, with the custom React script for Typescript, so that we can keep the zero configuration and ease of use. A good article on setting up a React app with TypeScript was written by Trey Huffine and can be found here.
我將為該項目使用create-react-app
以及用于Typescript的自定義React腳本,以便我們可以保持零配置和易用性。 Trey Huffine寫了一篇有關使用TypeScript設置React應用程序的好文章,可以在這里找到。
I definitely suggest looking at that post for some more in depth set up. But without further ado, we are going to run the following line in the terminal.
我絕對建議您查看該帖子以進一步了解更多信息。 但是事不宜遲,我們將在終端中運行以下行。
create-react-app weather --scripts-version=react-scripts-tsnpm install --save core-decorators
I’ll get to the decorators a little later. Just know that it’s a neat little feature that I was really excited to try out. But to be able to use it, we’ll have to edit our tsconfig.json
file to include experimental decorators. To do this, just add the bold line of code.
我待會再去裝修。 只是知道這是一個很好的小功能,我真的很興奮能嘗試一下。 但是要使用它,我們必須編輯tsconfig.json
文件以包含實驗裝飾器。 為此,只需添加粗體代碼。
{ "compilerOptions": {// ...code hidden... "noUnusedLocals": true, "experimentalDecorators": true } // ...more code hidden...}
And since I have Prettier installed on my development environment, I had to change my tslint.json
file because the lint conflicted with the formatter. If you have a similar development set up, I suggest just deleting all the tslint rules so that you don’t have to get bogged down on configuration. The file should look like this after you’re done.
而且因為我更漂亮對我的開發環境中安裝,我不得不改變我tslint.json
文件,因為皮棉與格式沖突。 如果您進行了類似的開發,建議您刪除所有的tslint規則,這樣就不必陷入配置問題。 完成后,文件應如下所示。
The folder structure that I will be using will look like the following. You can create, delete, and move files accordingly.
我將使用的文件夾結構如下所示。 您可以相應地創建,刪除和移動文件。
weather-app/├─ .gitignore├─ node_modules/├─ public/├─ src/ └─ assets/ | - - loader.svg | - - logo.svg └─ components/ | - - Weather.tsx | - - WeatherDisplay.tsx └─ styles/ | - - App.css | - - WeatherDisplay.css | — — index.tsx | — — registerServiceWorker.ts | — — App.tsx | — — index.css | - - config.ts | - - types.ts├─ package.json├─ tsconfig.json├─ tsconfig.test.json└─ tslint.json
Okay, the worst is over! We have finally set up our app. Let’s dive into the code.
好吧,最糟糕的時期已經過去了! 我們終于建立了我們的應用程序。 讓我們深入研究代碼。
步驟1:樣式 (Step 1: Styling)
I want to get the styling out of the way first. I’m not much of a designer, so all I really did was re-skin the create-react-app
default styles to have the freeCodeCamp green theme. Additionally I made the button more button-like and of course, more green. You are free to go wild with this if you happen to be a CSS master. You can also download image files here and place them in your assets/
folder.
我想先取消樣式。 我不是一個設計師,所以我真正要做的只是重新create-react-app
了create-react-app
默認樣式,使其具有freeCodeCamp綠色主題。 另外,我使按鈕更像按鈕,當然也更綠色。 如果您碰巧是CSS大師,則可以隨意使用。 您也可以在此處下載圖像文件,并將其放置在assets/
文件夾中。
第2步:好的,我撒謊了……更多設置 (Step 2: Okay, I lied… More Set Up)
But don’t worry, it’s actual code this time. First let’s start with the easy part: adding your API and API keys. Nothing new here — it looks exactly like normal JavaScript so far.
但是不用擔心,這是實際的代碼。 首先讓我們從簡單的部分開始:添加您的API和API密鑰。 這里沒什么新鮮的-到目前為止,它看起來完全像普通JavaScript。
Now for the TypeScript specific thing, we have to specify types. Well, we don’t have to, but we definitely should. The reason behind static typing is that it gives us security. Unlike normal JavaScript, our code won’t run if things are of the wrong type. Essentially this means that the compiler just flat out won’t let us write bad code.
現在,對于特定于TypeScript的東西,我們必須指定類型。 好吧,我們沒有必要,但是我們絕對應該。 靜態類型背后的原因是它為我們提供了安全性。 與普通JavaScript不同,如果類型錯誤,我們的代碼將無法運行。 從本質上講,這意味著編譯器只會讓我們無法編寫錯誤的代碼。
As you can see, it’s not too scary. Just add the type after a colon. The primitive types (string, number, boolean) are supported out of the gate. With objects, it is a good idea to create a new type specific to that particular object as seen in WeatherData
with DisplayLocation
.
如您所見,它并不太嚇人。 只需在冒號后面添加類型即可。 外邊支持原始類型(字符串,數字,布爾值)。 對于對象,最好創建一個特定于該特定對象的新類型,如使用DisplayLocation
WeatherData
。
Now, I was a little lazy, because the shape of the data coming from our API is a lot larger, and I could have created the whole object. But I opted to just take what I needed and discard the rest, which is why this types.ts
file is as small as it is.
現在,我有點懶了,因為來自我們的API的數據形狀要大得多,而且我可以創建整個對象。 但是我選擇了我需要的東西,而丟棄了其余的東西,這就是為什么types.ts
文件是如此之小的原因。
第3步:做出React-有趣的部分 (Step 3: React — The Fun Part)
I’m going to skip over the index.tsx
and App.tsx
files because there’s really nothing really new there. Just know that the imports are different because of how strict TypeScript is about modules. Instead, we’re going to go over the presentational component first.
我將跳過index.tsx
和App.tsx
文件,因為那里確實沒有什么新東西。 只是知道導入是不同的,因為TypeScript對模塊的要求非常嚴格。 相反,我們將首先介紹演示組件。
I still prefer to destructure Component
and Fragment
from React, instead of calling React.Component
, as it reduces redundancy. And for Fragments, if you’ve never played with them before, it’s basically a div that doesn’t show up in the HTML markup.
我仍然更喜歡從React解構Component
和Fragment
,而不是調用React.Component
,因為它減少了冗余。 對于Fragments,如果您以前從未使用過它們,則基本上是一個div,不會在HTML標記中顯示。
You will also notice that I have added interfaces at the top. An interface specifies what our props and state should look like. And if you haven’t noticed, TypeScript’s gimmick is adding types to everything, so that is what’s happening above within the angle brackets <Props, Sta
te>. If you are familiar with prop types, it does the same thing, but I feel like this is much cleaner.
您還將注意到,我在頂部添加了接口。 接口指定了我們的道具和狀態。 而且,如果您沒有注意到,TypeScript的花招就是為所有內容添加類型,因此,這就是尖括號<Props, Sta
te>中上面發生的事情。 如果您熟悉prop類型,它會做同樣的事情,但是我覺得這要干凈得多。
The next thing is the weird @
symbol. Well, that’s a decorator! I originally wanted to hook up Redux and connect so that I can show a much more complicated version, but the autobind
will do for now.
接下來是@
符號。 好吧,那是個裝飾! 我最初想連接Redux并進行連接,以便可以顯示更復雜的版本,但是autobind
暫時可以使用。
A decorator is basically a function that wraps around the class and applies necessary attributes. It also allows us to use export default
at the top, which is just a personal preference of mine.
裝飾器基本上是一個包裝類并應用必要屬性的函數。 它還允許我們在頂部使用export default
,這只是我的個人喜好。
@decorateexport default Class {}
// is the same as
export default decorate(Class)
In this case autobind will, as the name entails, automatically bind this
to everything so we don’t have to worry about binding issues. And coming from a more Object Oriented language, these class methods will look a lot cleaner than the JavaScript work-around with the arrow functions.
在這種情況下autobind會,正如其名稱限嗣繼承,自動綁定this
一切,所以我們沒有關于綁定的問題擔心。 而且,這些類方法來自一種更加面向對象的語言,看上去比帶箭頭功能JavaScript解決方法干凈得多。
classMethod = () => { console.log('when you use arrows, you don't have to worry about the keyword "this"');}
classMethod () { console.log('because of javascript, you have to worry about the keyword "this" here');}
And now finally we move to the bulk of our logic, which is going to be living in the Weather.tsx
component.
現在,最后我們轉到邏輯的大部分,它將Weather.tsx
在Weather.tsx
組件中。
The first thing you’ll notice is the ?
in the interface. I mentioned that we definitely should define types for our props, but what happens when you know for certain it won’t be defined until after the API call? Well we can define optional types with a question mark.
您會注意到的第一件事是?
在界面中。 我提到我們絕對應該為道具定義類型,但是當您確定要等到API調用之后才能定義它時,會發生什么情況? 好吧,我們可以用問號定義可選類型。
What is happening in the background is that the variable weatherData
is only allowed to be a WeatherData
type or undefined. Also, remember that our WeatherData
type is only a subsection of what wunderground offers. Earlier I mentioned that we are only going to take the data that we needed from the API — well, that’s what that huge destructuring on line 55 is doing.
在后臺發生的事情是,僅允許變量weatherData
為WeatherData
類型或未定義。 另外,請記住,我們的WeatherData
類型只是Wunderground提供的內容的一部分。 之前我提到過,我們只會從API中獲取所需的數據-好的,這就是第55行的巨大分解工作。
Did I mention you can specify expected return types of functions? That’s what is happening here with getCurrentPosition
, because I wanted to make sure that it returns a promise.
我是否提到過您可以指定函數的期望返回類型? 這就是getCurrentPosition
在這里發生的事情,因為我想確保它返回一個諾言。
The reasoning here is that I didn’t want to call getCurrentWeather
until after we had the correct geolocation, which means we’re dealing with asynchronous events. Async always means Promises, so that’s what’s going to happen.
這里的理由是,直到我們有了正確的地理位置之后,我才想調用getCurrentWeather
,這意味著我們正在處理異步事件。 異步總是意味著Promises,這就是要發生的事情。
A word of warning: the native geolocation API does take a long time to get a result without passing in any options. I opted to not add options to it as it was giving me errors at the time.
提示:本地地理位置API確實需要很長時間才能獲得結果,而無需傳遞任何選項。 我選擇不添加選項,因為當時它給了我錯誤。
And I believe that is all the new things happening in this app because of TypeScript. Everything else should be familiar if you know React. But hopefully you can see the benefits of this superset, as it adds both security to our code as well as some nice super powers.
而且我相信,由于TypeScript的緣故,此應用程序中正在發生所有新的事情。 如果您了解React,其他所有事情都應該熟悉。 但是希望您能看到此超集的好處,因為它既增加了我們代碼的安全性,又增加了一些不錯的超能力。
步驟4:完成! (Step 4: Complete!)
You did it! You finished an app that shows the weather at your current position. And in doing so, you’ve covered a good chunk of TypeScript as well as incorporating it into React.
你做到了! 您完成了一個顯示當前位置天氣的應用程序。 這樣做時,您涵蓋了很多TypeScript并將其合并到React中。
Of course, there can definitely be improvements on this, like an option to search and show other locations. And the UI can definitely be worked on. But if you haven’t already finished the weather app on freeCodeCamp, you have already gone above and beyond on this assignment.
當然,在此方面肯定可以進行改進,例如可以搜索并顯示其他位置。 UI絕對可以使用。 但是,如果您尚未在freeCodeCamp上完成氣象應用程序,那么您已經超出了這項任務。
翻譯自: https://www.freecodecamp.org/news/weather-in-react-and-typescript-4f774fc07be7/