كيف صممت تطبيق الطقس في freeCodeCamp باستخدام React و Typescript

لذلك قررت أخيرًا العودة إلى freeCodeCamp ومحاولة إنهاء شهادة تطوير الواجهة الأمامية. كنت قد انتهيت بالفعل من جميع الخوارزميات والبرامج التعليمية في وقت سابق من العام الماضي ، والشيء الوحيد المفقود هو المشاريع.

ولكن الآن بعد أن أصبحت أكثر خبرة كمطور Full Stack ، فإن معظم المشاريع سهلة بعض الشيء بالنسبة لمستواي الحالي. لذلك كان لدي خياران. يمكنني إما العودة إلى الأساسيات وإنهائها جميعًا في يوم واحد ، أو يمكنني قتل عصفورين بحجر واحد: استمتع ببعض المرح واختبر التكنولوجيا أثناء العمل في هذه المشاريع. أنا اختار هذا الأخير.

لكن دعونا نجعل هذه الطيور الثلاثة - لأنني كنت أرغب في كتابة شيء تعليمي / إرشادي لفترة من الوقت. اليوم ، ما سنقوم بمعالجته هو مشروع Show The Local Weather. لكن هذه المرة ، ستجمع بين React و Typescript! يمكنك إلقاء نظرة على الكود النهائي في GitHub repo ، بالإضافة إلى عرض توضيحي مباشر هنا.

خلفية

لذلك أول شيء أولاً: لماذا أرغب في القيام بذلك؟ حسنًا ، هذا هو الشيء: لقد كنت أقفز ذهابًا وإيابًا مع Angular 5 و React لبعض الوقت الآن. وأنا أحب React أكثر كإطار عمل. إنه صغير وموجز ، ولكنه يحتوي على جميع الميزات التي تحتاجها لإنشاء تطبيق صفحة واحدة كامل الوظائف. بالنسبة إلى Angular ، فهو كبير جدًا بالنسبة لي للاستمتاع بتطبيق صغير مثل هذا ... ولكنه يستخدم Typescript!

TypeScript هو مجموعة فائقة من JavaScript تضيف الكثير من الميزات المفقودة من JavaScript ، حتى مع التحسينات من ES6 / 7. تشتهر في الغالب بالكتابة الثابتة. لذلك تساءلت عما إذا كان بإمكاني الحصول على أفضل ما في العالمين. كانت الإجابة نعم مدوية! ... لم يتم تضمين Redux. (أعني أنه يمكنك تضمين Redux ، ولكن من الصعب إعداده حتى الآن ، لذلك لن أفعل ذلك في هذا الدليل).

بالنسبة لهذا المشروع ، سنركز على الحد الأدنى من قصص المستخدمين ، لأن تركيزي ينصب على التكنولوجيا وليس أي ميزات إضافية. على هذا النحو ، فإن واجهة برمجة التطبيقات التي سنستخدمها لهذا التطبيق ستكون Wunderround. إنها مثالية لما نبنيه ، لأنها توفر درجات حرارة في كل من فهرنهايت ودرجة مئوية ، كما أنها توفر رموزًا لظروف الطقس المختلفة. هذا يعني عمل برنامجي أقل من جانبنا.

الخطوة 0: الإعداد

سأكون باستخدام create-react-appلهذا المشروع، مع العرف يردون سيناريو نسخة مطبوعة على الآلة الكاتبة، حتى نتمكن من الحفاظ على التكوين الصفر، وسهولة الاستخدام. كتب Trey Huffine مقالة جيدة حول إعداد تطبيق React باستخدام TypeScript ويمكن العثور عليها هنا.

أقترح بالتأكيد البحث في هذا المنشور للحصول على مزيد من الإعداد المتعمق. ولكن بدون مزيد من اللغط ، سنقوم بتشغيل السطر التالي في المحطة.

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لأن النسالة تتعارض مع المنسق. إذا كان لديك تطوير مماثل ، أقترح حذف جميع قواعد 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. يمكنك أيضًا تنزيل ملفات الصور هنا ووضعها في assets/مجلدك.

الخطوة 2: حسنًا ، لقد كذبت ... المزيد من الإعداد

لكن لا تقلق ، إنه رمز فعلي هذه المرة. لنبدأ أولاً بالجزء السهل: إضافة مفاتيح API و API. لا شيء جديد هنا - يبدو تمامًا مثل JavaScript العادي حتى الآن.

الآن بالنسبة إلى الشيء المحدد لـ TypeScript ، علينا تحديد الأنواع. حسنًا ، لسنا مضطرين لذلك ، لكن يجب علينا بالتأكيد. السبب وراء الكتابة الثابتة هو أنها تمنحنا الأمان. على عكس JavaScript العادي ، لن يتم تشغيل الكود الخاص بنا إذا كانت الأشياء من النوع الخطأ. هذا يعني بشكل أساسي أن المترجم لن يسمح لنا بكتابة تعليمات برمجية سيئة.

كما ترى ، الأمر ليس مخيفًا جدًا. فقط أضف النوع بعد النقطتين. يتم دعم الأنواع الأولية (سلسلة ، رقم ، منطقية) خارج البوابة. مع الأشياء، انها فكرة جيدة لإنشاء نوع خاص جديد لهذا الكائن معين كما رأينا في WeatherDataو DisplayLocation.

الآن ، كنت كسولًا بعض الشيء ، لأن شكل البيانات القادمة من واجهة برمجة التطبيقات الخاصة بنا أكبر بكثير ، وكان بإمكاني إنشاء الكائن بأكمله. لكنني اخترت فقط أخذ ما أحتاجه وتجاهل الباقي ، ولهذا السبب هذا types.tsالملف صغير كما هو.

الخطوة 3: رد الفعل - الجزء الممتع

انا ذاهب لتخطي index.tsxو App.tsxالملفات لأن هناك حقا أي شيء حقا جديدة هناك. فقط اعلم أن عمليات الاستيراد مختلفة بسبب مدى صرامة TypeScript فيما يتعلق بالوحدات النمطية. بدلاً من ذلك ، سننتقل إلى عنصر العرض أولاً.

ما زلت أفضل التدمير Componentومن FragmentReact ، بدلاً من الاتصال 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!

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.