توسعه یک اپلیکیشن هواشناسی با React.js - بخش دوم
اپلیکیشن واقعی که قصد ایجاد آن را داریم، یک اپلیکیشن آبوهوا است که شرایط کنونی و پیشبینی هفتروز هفته را نمایش میدهد.
میتوانید نمونهی ارائه شده را در مرورگر خود، از طریق لینک زیر مشاهده کنید:
blog.mxstbr.com/weather-app
دارالترجمه رسمی پارسیس شامل خدمات ترجمه رسمی و تخصصی در بیش از 60 زبان زنده دنیا
بهترین افزونه های سئو وردپرس به صورت کاملا فارسی
فرم ساز آسان اولین فرم ساز کاملا فارسی وردپرس
خرید انواع ورق گالوانیزه رنگی با بهترین قیمت
بهترین کارگاه رویه کوبی و تعمیر مبل راحتی و استیل در تهران با قیمت و کیفیت عالی
پیشنیازها
Node.js یک زماناجرای جاوااسکریپت برای ترمینال شما میباشد. این تکنولوژی را میتوان به وسیلهی برخی ابزارها که برای ایجاد اپلیکیشن خود استفاده خواهیم کرد، بهکار برد. اگر قبلا نصب نکرده باشید (با اجرای دستور node –v در ترمینال خود چک کنید)، به سایت nodejs.org مراجعه کرده و طبق دستورالعمل ارائهشده، آخرین نسخهی مربوطه (نسخه v6 در زمان نوشتن این مقاله) را نصب کنید.گام اول
اخیرا فیسبوک، منبع باز یک ابزار کوچک خوب به نام create-react-app ارائه کرده، که امکان شروع راحت با اپلیکیشن React را برای ما فراهم میکند. همچنین شامل تمامی ابزارهای ساخت ضروری و گامهای نفوذ، جهت انجام کارها میباشد.این اپلیکیشن با دستور npm بهصورت زیر نصب میشود:
npm install -g create-react-app
بهمحض اتمام نصب، میتوانید به دستور create-react-app در پایانهی خود دسترسی داشته باشید. در ادامه اپلیکیشن آبوهوا را بهصورت اساسی ایجاد میکنیم:
create-react-app weather-app
آرگومان create-react-app که در نمونهی ما weather-app هست، نام پوشهای که قرار است ایجاد شود را برای برنامه مشخص میکند. از آنجایی که اپلیکیشن آبوهوا مدنظر میباشد، بهتر است از همین نام استفاده شود.
اگر به فایل src/index.js مراجعه کنید، کد زیر را مشاهده خواهید کرد:
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';
ReactDOM.render(
<App />,
document.getElementById('root')
);
از آنجایی که create-react-app شامل یک سرور ساده است، بنابراین بهجای باز کردن فایل index.html بهصورت دستی، میتوان دستور npm run start را در مسیر weather-app اجرا کرده و اپلیکیشن خود را در localhost:3000 مشاهده کرد!
اگر به مؤلفهی src/App.js مراجعه کنید، گروهی از کدهای استاندارد در آن مشاهده خواهید کرد. دستور import logo from './logo.svg'; (و فایل logo.svg در صورت دلخواه) و تمام JSXها را حذف کرده و بهجای آنها، یک عنوان با نام "Weather" ارائه دهید:
// App.js
import React from 'react';
import './App.css';
class App extends React.Component {
render() {
return (
<h1> Weather </h1>
);
}
}
export default App;
اگر فایل مربوطه را ذخیره کرده و به مرورگرتان برگردید، عنوان "Weather" را مشاهده میکنید. اما وظیفهی import و export چیست؟
ماژولها
اپلیکیشنهای دنیای واقعی میتوانند شامل هر تعداد مؤلفه باشند. قرار دادن همهی این مولفهها در یک فایل عملی نیست؛ بنابراین آنها را بهصورت یک ماژول ایجاد میکنیم. روش فوق این امکان را فراهم میکند که اپلیکیشنهایمان بهخوبی سازمان یافته و بهراحتی بتوان با آن کار کرد. کاری که انجام داده شد، مؤلفهی App نامیده میشود که از ماژول react و App.css استفاده میکند!
ماژولها را میتوان از طریق خارج کردن چیزی از فایل، مثل خارج کردن مؤلفهی App در بالا ایجاد کرد. سپس این مؤلفه میتواند به فایل دیگر با دستور import App from './path/to/App.js' وارد شود. (در واقع با مراجعه به فایل index.js، اگر در حال انجام باشد خواهید دید!)
ماژولهای Node
همانطور که اشاره شد، کاری که در زمان اجرای دستور npm install انجام داده شد، نصب یک ماژول میباشد. این بدین معنی است که یک نفر ماژولی (مثل ماژول App ذکر شده) را در npm (Node Package Manager) قرار داده است که بعدا میتوان نصب کرده و در کد خود استفاده کنید!
روشی که از React استفاده کرده و اپلیکیشن خود را بدون ضمیمه کردن چیزی ایجاد میکنیم، یک مزیت بزرگ در مورد فهمیدن آنچه در جریان است میباشد!
خب، به اپلیکیشن آبوهوای خودمان برگردیم.
بهمنظور اینکه اپلیکیشن مورد نظر خوب به نظر بیاد، به کمی طراحی نیاز داریم. از آنجایی که برایتان آماده کردیم، میتوانید روی React تمرکز کنید و به راحتی تمام فایلهای CSS موجود در App.css را جایگزین کنید.
همچنین در اپلیکیشن خود باید مکانی که اطلاعات آبوهوای آن نیاز است، مشخص باشد؛ از اینرو، یک فرم با یک ورودی و برچسبی با عنوان"City, Country" اضافه میکنیم!
// App.js
class App extends React.Component {
render() {
return (
<div>
<h1> Weather </h1>
<form>
<label> I want to know the weather for
<input placeholder={"City, Country"} type="text" />
</label>
</form>
</div>
);
}
}
همانطور که در کد مشاهده میکنید، برچسب input درون برچسب label قرار داده شده است. از اینرو، زمانی که کاربران روی label کلیک میکنند، input جهت دریافت ورودی انتخاب میشود!
زمانی که در ورودی چیزی وارد کنید و دکمهی "Enter" را فشار دهید، صفحهی مورد نظر بهروز شده و هیچ اتفاقی رخ نمیدهد. چیزی که واقعا میخواهیم انجام دهیم، واکشی دادهها هنگام وارد کردن یکشهر و یککشور میباشد. از اینرو، یک کنترلکنندهی onSubmit به فرم و یکتابع fetchData به مؤلفهی خود اضافه میکنیم!
// App.js
class App extends React.Component {
fetchData = (evt) => {
evt.preventDefault();
console.log('fetch data!');
};
render() {
return (
<div>
<h1> Weather </h1>
<form onSubmit={this.fetchData}>
<label> I want to know the weather for
<input placeholder={"City, Country"} type="text" />
</label>
</form>
</div>
);
}
}
با اجرای evt.preventDefault() در تابع fetchData (چیزی که در زمان فشار دادن enter در فرم مربوطه فراخوانی میشود)، به مرورگر میگوییم که صفحهی موردنظر را بهروزرسانی نکند و بهجای آن، هر چیزی که میخواهد را نادیده گرفته و هرچه که ما بگوییم انجام دهد. واکشی دادهها هر زمان که فرم را ارسال کنید، بارها و بارها وارد سیستم کنسول میشود. چگونه شهر و کشور وارد شده را به تابع مورد نظر وارد میکنیم؟
با ذخیره کردن مقدار ورودی در حالت مؤلفهی محلی خود، میتوان آن را از متد مربوطه بهدست آورد. زمانی که این کار را انجام میدهیم، ورودی ما به اصطلاح یک «ورودی کنترل شده» محسوب میشود.
مکان وارد شده کنونی در this.state.location ذخیره شده و یک متد کاربردی به نام changeLocation به مؤلفهی خود اضافه میکنیم که متن ورودی را onChange کرده و حالت مربوطه را با متن کنونی مقداردهی میکند:
// App.js
class App extends React.Component {
fetchData = (evt) => { /* … */ };
changeLocation = (evt) => {
this.setState({
location: evt.target.value
});
};
render() {
return (
<div>
<h1> Weather </h1>
<form onSubmit={this.fetchData}>
<label> I want to know the weather for
<input
placeholder={"City, Country"}
type="text"
value={this.state.location}
onChange={this.changeLocation}
/>
</label>
</form>
</div>
);
}
}
همانطور که در فصل اول اشاره شد، زمانی که چیزی در حالت محلی خود ذخیره شود باید بهصورت کد زیر از قبل تعریف شود:
// App.js
class App extends React.Component {
state = {
location: ''
};
fetchData = (evt) => { /* … */ };
changeLocation = (evt) => {
this.setState({
location: evt.target.value
});
};
render() {
return (
<div>
<h1> Weather </h1>
<form onSubmit={this.fetchData}>
<label> I want to know the weather for
<input
placeholder={"City, Country"}
type="text"
value={this.state.location}
onChange={this.changeLocation}
/>
</label>
</form>
</div>
);
}
}
در تابع fetchData، بعدا میتوان به this.state.location برای بهدست آوردن مکان کنونی دسترسی پیدا کرد:
// App.js
class App extends React.Component {
state = { /* … */ };
fetchData = (evt) => {
evt.preventDefault();
console.log('fetch data for', this.state.location);
};
changeLocation = (evt) => { /* … */ };
render() { /* … */ }
}
اکنون هر مکانی که وارد کنید بایستی «واکشی داده برای MyCity, MyCountry» وارد شود.
واکشی دادهها
در این بخش به معرفی واکشی دادهها میپردازیم. بهجای کنسول ورود یک متن، به برخی اطلاعات آبوهوا نیاز داریم. برای این کار، از OpenWeatherMap API استفاده میشود که یک سرویس رایگان، جهت دسترسی به دادههای تمام مکانهای موجود در کل جهان را فراهم میکند. از اینرو یک کلید API نیاز دارید، پس به آدرس openweathermap.org/api رفته و در نوار بالا از طریق بخش "Sign Up" برای یک اکانت رایگان ثبتنام کنید.
بهمحض ثبتنام از طریق home.openweathermap.org/api_keys به صفحهکلید API خود رفته و کلیدAPI را از آنجا کپی و در جایی امن نگهداری کنید.
اکنون که میتوان به کلیهی اطلاعات آبوهوا دسترسی داشت، به اپلیکیشن خود ادامه میدهیم!
درون تابع fetchData، باید یک درخواست جهت API بدهیم؛ از اینرو میخواهم از یک ماژول npm که xhr نامیده میشود، استفاده کنیم که پوشهای میشود پیرامون JavaScript XMLHttpRequest سبب آسان شدن درخواستها. دستور زیر را اجرا کنید:
npm install --save xhr
درحالی که ماژول مربوطه نصب میشود، آن را در بالای مؤلفهی API خود وارد کنید:
// App.js
import React from 'react';
import './App.css';
import xhr from 'xhr';
class App extends React.Component { /* … */ };
برای دریافت دادهها، ساختار URLای که درخواست خواهیم کرد مثل دستور زیر میباشد:
http://api.openweathermap.org/data/2.5/forecast?q=CITY,COUNTRY&APPID=YOURAPIKEY&units=metric
CITY,COUNTRY را با شهر و کشور انتخابی، YOURAPIKEY را با کلید API کپی شدهی خود، جایگزین کنید. سپس URL فوق را در مرورگر خود باز کنید، که بهصورت زیر میباشد:
http://api.openweathermap.org/data/2.5/forecast?q=Vienna,Austria&APPID=asdf123&units=metric
آنچه شما دریافت خواهید کرد یک شئ JSON شامل ساختار زیر است:
"city": {
"id": 2761369,
"name": "Vienna",
"coord": {
"lon": 16.37208,
"lat": 48.208488
},
"country": "AT",
"population": 0,
"sys": {
"population": 0
}
},
"cod": "200",
"message": 0.0046,
"cnt": 40,
"list": [ /* Hundreds of objects here */ ]
آرایهی list سطح بالا، شامل اطلاعات آبوهوای پنجروز آینده میباشد که بر حسب زمان مرتب شده است. یکی از اشیاء آبوهوا بهصورت زیر میباشد: (تنها خطوط مربوطه نمایش داده شده است)
{
"dt": 1460235600,
"main": {
"temp": 6.94,
"temp_min": 6.4,
"temp_max": 6.94
},
"weather": [
{
"main": "Rain",
/* …more data here */
}
],
/* …more data here */
}
پنجویژگی که برای ما اهمیت دارد عبارتاند از: dt_txt زمان پیشبینی آبوهوا، temp دمای مورد انتظار، temp_min و temp_max بهترتیب کمترین و بیشترین دمای مورد انتظار و weather[0].main شرح آبوهوا در آن زمان را مشخص میکنند.OpenWeatherMap اطلاعات بسیار زیادی که دور از تصور است، در اختیار ما قرار میدهد. توصیه میکنم کمی بیشتر اطراف را جستجو کرده و ببینید چهچیزی میتوان استفاده کرد تا اپلیکیشن جامعتر شود.
اکنون که میدانیم چهچیزی نیاز است، به این مسأله میپردازیم که چگونه دادهها را بهطور واقعی واکشی کنیم؟ (در حال حاضر نصب xhrبایستی به پایان رسیده باشد)
روال عمومی xhr بهصورت زیر میباشد:
xhr({
url: 'someURL'
}, function (err, data) {
/* Called when the request is finished */
});
همانطور که مشاهده میشود، تمام چیزهایی که واقعا برای ما اهمیت دارد ساخت URL و ذخیره کردن دادههای بازگشتی در محلی میباشد.
میدانیم که URL مورد نظر دارای یک پیشوند است که همیشه همان http://api.openweathermap.org/data/2.5/ forecast?q=و دارای یک پسوند که همیشه همان&APPID=YOURAPIKEY&units=metric میباشد. تنها کاری که نیاز است انجام دهیم، افزودن مکانی است که کاربر به URL وارد میکند!
همچنین میتوانید واحدهایی که دوباره بهدست آوردید را از طریق مقداردهی units با دستور زیر تغییر دهید:
imperial: http://api.openweathermap.org/data/2.5/forecast?q=something&APPID=YOURAPIKEY&units=imperial
اکنون اگر به این فکر میکنید که ممکن است کاربر در ورودی کاراکتر فاصله را وارد کند، آنگاه میدانید چه اتفاقی رخ خواهد داد؛ از آنجایی که URL با کاراکترهای فاصله معتبر نیست، درنتیجه کار نخواهد کرد و همهچیز متوقف میشود. این موضوع درست است، اما جاوااسکریپت یک متد بسیار ساده برای رهایی از کاراکترهای غیر مجاز URL ارائه میدهد. این متد encodeURIComponent() نامیده میشود و نحوهی استفادهی آن بهصورت زیر است:
encodeURIComponent('My string with spaces'); // -> 'My%20string%20with%20spaces'
متد فوق را با ساختار URL مورد نیاز، شرح xhr و حالت مؤلفه ترکیب ک و پس از کسب تمام اجزای مورد نیاز میتوان دادهها را از سرور دریافت کرد.
لطفا توجه کنید که ممکن است نیاز داشته باشید سرور توسعه داده شده را دوباره راهاندازی کنید (CTRL-C جهت توقف آن و npm start جهت آغاز دوباره) که برای این کار یک ماژول جدید نصب شده است!
ابتدا مکان از حالت مربوطه کدگذاری میشود:
// App.js
import React from 'react';
import './App.css';
import xhr from 'xhr';
class App extends React.Component {
state = { /* … */ };
fetchData = (evt) => {
evt.preventDefault();
var location = encodeURIComponent(this.state.location);
};
changeLocation = (evt) => { /* … */ };
render() { /* … */ }
}
سپس URL مورد نیاز که برای رهایی از مکان استفاده شده، ساخته میشود:
// App.js
import React from 'react';
import './App.css';
import xhr from 'xhr';
class App extends React.Component {
state = { /* … */ };
fetchData = (evt) => {
evt.preventDefault();
var location = encodeURIComponent(this.state.location);
var urlPrefix = 'http://api.openweathermap.org/data/2.5/forecast?q=';
var urlSuffix = '&APPID=YOURAPIKEY&units=metric';
var url = urlPrefix + location + urlSuffix;
};
changeLocation = (evt) => { /* … */ };
render() { /* … */ }
}
آخرین مورد جهت دریافت دادهها از سرور، فراخوانی xhr با URL فوق میباشد:
// App.js
import React from 'react';
import './App.css';
import xhr from 'xhr';
class App extends React.Component {
state = { /* … */ };
fetchData = (evt) => {
evt.preventDefault();
var location = encodeURIComponent(this.state.location);
var urlPrefix = 'http://api.openweathermap.org/data/2.5/forecast?q=';
var urlSuffix = '&APPID=YOURAPIKEY&units=metric';
var url = urlPrefix + location + urlSuffix;
xhr({
url: url
}, function (err, data) {
/* …save the data here */
});
};
changeLocation = (evt) => { /* … */ };
render() { /* … */ }
}
از آنجایی که به React جهت ارائهی دوبارهی اپلیکیشن خود هنگام لود شدن دادهها احتیاج داریم، باید آن را در حالت مؤلفه App خود ذخیره کنیم. همچنین درخواست داده شبکه یک رشته میباشد، از اینرو باید آن را به وسیلهی JSON.parse بهصورت یک شئ ایجاد کرد.
// App.js
import React from 'react';
import './App.css';
import xhr from 'xhr';
class App extends React.Component {
state = { /* … */ };
fetchData = (evt) => {
evt.preventDefault();
var location = encodeURIComponent(this.state.location);
var urlPrefix = 'http://api.openweathermap.org/data/2.5/forecast?q=';
var urlSuffix = '&APPID=YOURAPIKEY&units=metric';
var url = urlPrefix + location + urlSuffix;
var self = this;
xhr({
url: url
}, function (err, data) {
self.setState({
data: JSON.parse(data.body)
});
});
};
changeLocation = (evt) => { /* … */ };
render() { /* … */ }
}
نکته: var self = this; ضروری است، چرا که (== this) از تابع داخلی بهمدت طولانی مؤلفه نبوده، بلکه تابع داخلی میباشد.
دادهی مورد نظر را در حالت خود تعیین میکنیم:
// App.js
import React from 'react';
import './App.css';
import xhr from 'xhr';
class App extends React.Component {
state = {
location: '',
data: {}
};
fetchData = (evt) => { /* … */ };
changeLocation = (evt) => { /* … */ };
render() { /* … */ }
}
اکنون که اطلاعات آبوهوا برای مکان خواسته شده در حالت مؤلفهی خود دریافت شده است، میتوان آن را در متد ارائه شدهی خودمان بهکار ببریم. یادتان باشد اطلاعات آبوهوای کنونی در آرایه list، بر اساس زمان مرتب شده بود. بنابراین اولین عضو آرایهی فوق، دمای کنونی میباشد که ارائه داده میشود:
// App.js
import React from 'react';
import './App.css';
import xhr from 'xhr';
class App extends React.Component {
state = { /* … */ };
fetchData = (evt) => { /* … */ };
changeLocation = (evt) => { /* … */ };
render() {
var currentTemp = 'not loaded yet';
if (this.state.data.list) {
currentTemp = this.state.data.list[0].main.temp;
}
return (
<div>
<h1> Weather </h1>
<form onSubmit={this.fetchData}>
<label> I want to know the weather for
<input
placeholder={"City, Country"}
type="text"
value={this.state.location}
onChange={this.changeLocation}
/>
</label>
</form>
<p className="temp-wrapper">
<span className="temp">{ currentTemp }</span>
<span className="temp-symbol"> °C </span>
</p>
</div>
);
}
}
در مرورگرتان این کار را انجام داده و مکان کنونی خود را وارد کنید تا دمای کنونی را مشاهده کنید. شگفت انگیز است!
خلاصهی این فصل
در این فصل نحوهی ایجاد اپلیکیشن خود را یاد گرفتیم و سپس یک ورودی متن کنترل شده ساخته و از آن جهت واکشی اولین دادهی خود از طریق xhr، استفاده کردیم.
اکنون که دمای کنونی در اختیار ماست، نیاز داریم پیشبینی پنجروز آینده را ارائه دهیم. در فصل سه که افزودن یک نمودار پیشبینی میباشد، نحوهی کشیدن یک نمودار را یاد خواهیم گرفت.
منبع: plot.ly
نظرات و سوالات کاربران
لطفا لطفا لطفا لطفا لطفا
اموزهاش رو بزارید
ممنون که مطالعه میکنید. بله حتما به روزرسانیها رو سعی میکنیم بهتر انجام بدیم.