Как изградих приложението за времето в freeCodeCamp с помощта на React и Typescript

Затова най-накрая реших да се върна на freeCodeCamp и да се опитам да попълня сертификата си за развитие на Front End. Вече бях завършил всички алгоритми и уроци в началото на миналата година и единственото, което липсваше, бяха проектите.

Но сега, когато имам повече опит като Full Stack Developer, повечето проекти са малко лесни за сегашното ми ниво. Така че имах два избора. Можех или да се върна към основите и да ги довърша всички за един ден, или да убия две птици с един камък: да се позабавлявам и да експериментирам с технологията, докато работя по тези проекти. Аз избрах второто.

Но нека направим това три птици - защото от известно време искам да напиша нещо като урок / ръководство. Днес това, с което ще се заемем, е проектът „Покажи местното време“. Но този път ще комбинира React и Typescript! Можете да разгледате готовия код в това репо GitHub, както и демонстрация на живо тук.

Заден план

Така че първото нещо първо: защо бих искал да направя това? Е, това е нещото: скачам напред и назад с Angular 5 и React от известно време. И харесвам React повече като рамка. Той е малък и кратък, но има всички функции, от които се нуждаете, за да създадете напълно функционално приложение за една страница. Що се отнася до Angular, той е твърде голям, за да се радвам на приложение, толкова малко, колкото това ... но използва Typescript!

TypeScript е супер набор от JavaScript, който добавя много функции, които просто липсват в JavaScript, дори и с подобренията от ES6 / 7. Известен е най-вече със статичното си писане. Затова се чудех дали мога да получа най-доброто от двата свята. Отговорът беше категоричен ДА! ... Redux не е включен. (Искам да кажа, че можете да включите Redux, но досега беше трудно да настроите, така че няма да го правя за това ръководство.)

За този проект ще се съсредоточим върху минимума от потребителските истории, защото моят фокус е технологията, а не каквито и да било допълнителни функции. Като такъв, API, който ще използваме за това приложение, ще бъде Wunderround. Той е идеален за това, което изграждаме, защото те предлагат температури както по Фаренхайт, така и по Целзий, а също така предоставят икони за различните метеорологични условия. Това означава по-малко програмна работа в нашия край.

Стъпка 0: Настройте

Ще използвам create-react-appза този проект с персонализирания React скрипт за Typescript, за да можем да запазим нулевата конфигурация и лекота на използване. Добра статия за настройване на приложение React с TypeScript е написана от Trey Huffine и може да бъде намерена тук.

Определено предлагам да разгледате тази публикация за по-задълбочена настройка. Но без повече шум ще пуснем следния ред в терминала.

create-react-app weather --scripts-version=react-scripts-tsnpm install --save core-decorators

Ще стигна до декораторите малко по-късно. Просто знайте, че това е страхотна малка функция, която наистина бях развълнувана да изпробвам. Но за да можем да го използваме, ще трябва да редактираме нашия tsconfig.jsonфайл, за да включим експериментални декоратори. За да направите това, просто добавете удебеления ред на кода.

{ "compilerOptions": {// ...code hidden... "noUnusedLocals": true, "experimentalDecorators": true } // ...more code hidden...}

И тъй като съм инсталирал Prettier на моята среда за разработка, трябваше да сменя tslint.jsonфайла си, защото lint е в конфликт с форматиращия. Ако имате настроена подобна разработка, предлагам просто да изтриете всички правила на tslint, за да не се налага да затъвате в конфигурацията. Файлът трябва да изглежда така след като приключите.

Структурата на папките, която ще използвам, ще изглежда по следния начин. Можете да създавате, изтривате и премествате файлове по съответния начин.

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

Добре, най-лошото свърши! Най-накрая настроихме нашето приложение. Нека да се потопим в кода.

Стъпка 1: Оформяне

Първо искам да махна стайлинга. Аз не съм особено дизайнер, така че всичко, което наистина направих, беше да преоформя create-react-appстиловете по подразбиране, за да има зелена тема freeCodeCamp. Освен това направих бутона по-бутонен и, разбира се, по-зелен. Можете да подивите с това, ако случайно сте CSS master. Можете също да изтеглите файлове с изображения тук и да ги поставите във вашата assets/папка.

Стъпка 2: Добре, излъгах ... Още настройка

Но не се притеснявайте, този път това е действителен код. Първо нека започнем с лесната част: добавяне на вашия API и API ключове. Тук няма нищо ново - досега изглежда точно като нормалния JavaScript.

Сега за специфичното за TypeScript нещо трябва да посочим типове. Е, не е нужно, но определено трябва. Причината за статичното писане е, че ни дава сигурност. За разлика от нормалния JavaScript, нашият код няма да работи, ако нещата са от грешен тип. По същество това означава, че компилаторът просто се проваля, няма да ни позволи да напишем лош код.

Както виждате, не е твърде страшно. Просто добавете типа след двоеточие. Примитивните типове (низ, число, булево) се поддържат извън портата. С обектите е добра идея да създадете нов тип, специфичен за този конкретен обект, както се вижда в WeatherDataс DisplayLocation.

Сега бях малко мързелив, защото формата на данните, идващи от нашия API, е много по-голяма и можех да създам целия обект. Но избрах просто да взема това, от което се нуждаех, и да изхвърля останалото, поради което този types.tsфайл е толкова малък, колкото е.

Стъпка 3: React - забавната част

Ще прескоча index.tsxи App.tsxфайловете, защото там наистина няма нищо наистина ново. Просто знайте, че импортирането е различно поради това колко строг е TypeScript за модулите. Вместо това първо ще разгледаме презентационния компонент.

Все още предпочитам да деструктурирам Componentи Fragmentот React, вместо да се обаждам React.Component, тъй като намалява излишъка. А за Fragments, ако никога досега не сте играли с тях, това е основно div, който не се показва в HTML маркировката.

Също така ще забележите, че съм добавил интерфейси в горната част. Интерфейсът посочва как трябва да изглеждат нашите подпори и състояние. И ако не сте забелязали, трикът на TypeScript добавя типове към всичко, така че това се случва по-горе в ъгловите скобиte>. If you are familiar with prop types, it does the same thing, but I feel like this is much cleaner.

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.

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.

@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.

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.

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.

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.

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.

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.

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.

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.

Step 4: Complete!

Original text


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.

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.