آموزش مقدماتی ری اکت – جامع و کاربردی

ری اکت چیست؟
ریکت یک کتابخانه جاوا اسکریپتی است که توسط شرکت فیسبوک توسعه داده شده است. ری اکت ابزاری است برای تولید کامپوننت های رابط کاربری (UI Components).
ری اکت چگونه کار می کند؟
در واقع ابتدا یک virtual DOM در حافظه می سازد و بجای اعمال تغییرات در DOM بطور مستقیم، تغییرات را در این DOM مجازی انجام داده و سپس به DOM اصلی مرورگر منتقل میکند.
ریکت فقط المانی را که باید آپدیت شود تغییر می دهد.
تاریخچه کتابخانه ReactJS:
نسخه فعلی ریکت 16.13.0 است که در تاریخ 26 فوریه 2020 میلادی عرضه شد.
ریکت اولین بار در سال 2011 میلادی توسط شرکت فیسبوک برای پیاده سازی بخش خبرخوان سایت فیسبوک معرفی شد. یکی از مهندسان فیسبوک بنام آقای Jordan Walke ریکت را ارائه کرد.
پکیج create-react-app نسخه 2 در ماه اکتبر 2018 میلادی عرضه شد که از Babel7 و WebPack4 و Jest23 پشتیبانی می کند.
شروع کار با کتابخانه ریکت:
برای شروع پیاده سازی اپلیکیشن توسط کتابخانه جاوا اسکریپتی ریکت، به دو روش می توانید اقدام کنید. اول اینکه cdn های ریکت را مستقیما در فایل html پروژه خود اضافه کنید. روش دوم: باید NPM و Node.js را نصب کنید.
تعریف مستقیم ریکت در html:
به منظور یادگیری سریع ریکت می توانید اسکریپت های کتابخانه ریکت را مستقیما بطور دستی در فایل html پروژه خود تعریف نمائید. مانند کد زیر:
<!DOCTYPE html> <html> <script src="https://unpkg.com/react@16/umd/react.production.min.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script> <script src="https://unpkg.com/babel-standalone@6.15.0/babel.min.js"></script> <body> <div id="mydiv"></div> <script type="text/babel"> class Hello extends React.Component { render() { return <h1>Hello World!</h1> } } </script> </body> </html>
شرح: دو خط اول به ما اجازه می دهد کدهای ریکت را در جاوا اسکریپت تعریف نمائیم. خط سوم هم به ما اجازه نوشتن JSX و ES6 را در مرورگرهای قدیمی می دهد.
در بخش های بعدی با نحوه نوشتن کدهای JSX بیشتر آشنا خواهید شد.
آماده سازی محیط توسعه ریکت:
توصیه می کنیم از روش اول یعنی تعریف مستقیم CDN های ریکت در فایل HTML استفاده نکنید. روش استاندارد شروع پیاده سازی اپلیکیشن با ریکت نصب Node.js و استفاده از دستورات npm می باشد.
بدین منظور ابتدا node.js را از آدرس زیر دانلود کرده و در سیستم خود نصب نمائید:
https://nodejs.org/en/download/
سپس روی فولدری که می خواهید پروژه ریکت خود را پیاده سازی کنید cmd را اجرا کنید. در مرحله بعد دستور npx create-react-app project_name را اجرا کنید.
npx create-react-app project_name
نصب توسط yarn:
yarn create react-app project_name
با اجرای دستور فوق یک فولدر بنام myfirstproject ایجاد می شود و تمام فایل های کتابخانه ریکت در آن ذخیره می شود.
نکته: اگر می خواهید پروژه خود را با زبان برنامه نویسی تایپ اسکریپت توسعه دهید، نیاز است دستور نصب ریکت را به شکل زیر تغییر دهید:
npx create-react-app project_name --template typescript # or yarn create react-app project_name --template typescript
اجرای پروژه ریکت:
پس از اینکه node package manager تمام فایل های ریکت را نصب کرد و پیغام موفقیت آمیز داد برای اجرای پروژه ریکت ابتدا باید توسط دستور cd به فولدر پروژه بروید.
cd myfirstproject
سپس با دستور npm start اپلیکیشن ریکتی خود را برای اولین بار اجرا کنید.
بطور اتوماتیک مرورگرتان باز خواهد شد و در یک تب یکه حاوی آدرس localhost:3000 می باشد پروژه ریکت شما اجرا خواهد شد. در صورتیکه این اتفاق نیوفتاد می توانید آدرس localhost:3000 را بطور دستی در نوار آدرس مرورگر تایپ کرده و اجرا کنید.
انجام تغییرات در پروژه ریکت:
تا اینجا خوب پیش رفتیم و توانستیم یک اپلیکیشن تحت وب را ایجاد کرده و اجرا کنیم. اما چطور می توانیم در کد این پروژه تغییراتی اعمال کنیم؟
وارد فولدر پروژه بنام myfirstproject شوید و در فولدر src فایل App.js را باز کنید. کدی شبیه قطعه کد زیر خواهد داشت:
import React, { Component } from 'react'; import logo from './logo.svg'; import './App.css'; class App extends Component { render() { return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> Edit <code>src/App.js</code> and save to reload. </p> <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer" > Learn React </a> </header> </div> ); } } export default App;
در کد فوق می توانید فعلا محتوای بخش html را ویرایش کرده و پروژه را ذخیره کنید تا نتیجه را در خروجی ببنید.
بعنوان مثال تگ <div className=”App”> را با یک <h1>Hello World!</h1> تعویض کنید:
import React, { Component } from 'react'; class App extends Component { render() { return ( <div className="App"> <h1>Hello World!</h1> </div> ); } } export default App;
برای مشاهده نتیجه در مرورگر کافیست پروژه را ذخیره کنید. بدون اینکه نیاز به ریلود کردن مرورگر باشد اپلیکیشن بروز خواهد شد.
خروجی زیر را خواهیم داشت:
مرحله بعدی چیست؟
اکنون شما محیط موردنیاز را برای توسعه یک اپلیکیشن تحت وب با ریکت را در سیستم خود فراهم کردید. وقت آنست که بیشتر درباره ریکت و دستورات آن بدانید. کدهای فایل index.js را مطابق کد زیر تعریف کنید:
import React from 'react'; import ReactDOM from 'react-dom'; const myfirstelement = <h1>Hello React!</h1> ReactDOM.render(myfirstelement, document.getElementById('root'));
و کد فایل index.html را مطابق کد زیر:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>React App</title> </head> <body> <div id="root"></div> </body> </html>
رندر کردن کدهای html توسط ریکت:
هدف ریکت رندر یا render کردن کدهای html در یک صفحه وب است که توسط دستور ReactDOM.render() آن را انجام می دهد.
تابع Render:
تابع render دو آرگومان می گیرد: اولی کد html است و دومی المان html
هدف تابع رندر در ریکت نمایش کد html در المنت html می باشد. بعنوان مثال در کد زیر می خواهیم پاراگراف را در المنت با آیدی root نمایش دهیم:
ReactDOM.render(<p>Hello</p>, document.getElementById('root'));
خروجی کد html به شکل زیر خواهد بود:
<body> <div id="root"> <p>Hello</p> </div> </body>
کد html:
در این مقاله آموزشی از JSX برای نوشتن کدهای HTML داخل کدهای جاوا اسکریپت استفاده می کنیم.
نگران یادگیری JSX نباشید. در بخش بعدی آن را کامل توضیح خواهیم داد.
در مثال زیر می خواهیم یک متغیر تعریف کنیم که داخل آن تگ جدول یا <table> در html قرار دارد و قصد نمایش آن را در المنت root پروژه داریم:
const myelement = ( <table> <tr> <th>Name</th> </tr> <tr> <td>John</td> </tr> <tr> <td>Elsa</td> </tr> </table> ); ReactDOM.render(myelement, document.getElementById('root'));
المان root در ریکت:
المان root در ریکت به المانی گفته می شود که می خواهیم نتیجه را نمایش دهیم. در واقع شبیه container برای محتوا یا content می باشد.
دقت کنید که المان روت لزوما نباید div باشد و همچنین آیدی root نباید باشد. بلکه می تواند بصورت زیر باشد:
<header id="sandy"></header>
و در کد زیر گفتیم که نتیجه در المان بالا نمایش یابد:
ReactDOM.render(<p>Hallo</p>, document.getElementById('sandy'));
JSX در ریکت چیست؟
عبارت JSX مخفف Javascript XML است که امکان نوشتن کدهای HTML را در بین کدهای جاوا اسکریپت به ما می دهد.
بدون اینکه نیاز باشد از توابع createElement() یا appendChild() استفاده کنیم توسط JSX می توان کدهای HTML را درون اسکریپت های JS تعریف کرد و در DOM قرار داد.
در واقع JSX کدهای HTML را به المان های ریکت تبدیل می کند. البته لزومی ندارد حتما از JSX در پروژه های ریکتی خود استفاده کنید اما استفاده از آن باعث راحتی نوشتن کدها خواهد شد.
در این بخش می خواهیم دو نمونه را خواهیم دید که در مثال اول از JSX برای نمایش خروجی در ریکت استفاده کرده ایم و در مثال دوم خیر:
مثال اول:
const myelement = <h1>I Love JSX!</h1>; ReactDOM.render(myelement, document.getElementById('root'));
مثال دوم:
const myelement = React.createElement('h1', {}, 'I do not use JSX!'); ReactDOM.render(myelement, document.getElementById('root'));
همانطور که می توانید در مثال اول ببینید، براحتی مقدار یک متغیر جاوا اسکریپتی را برابر کد HTML قرار دادیم و در خط بعدی آنرا در المان روت نمایش دادیم.
JSX یکی از مشتقات اکما اسکریپت نسخه 6 است که در زمان اجرای اپلیکیشن به کدهای جاوا اسکریپت کلاسیک تبدیل خواهد شد.
نحوه نوشتن کدهای JSX:
در JSX میتوانید عبارات جاوا اسکریپتی موردنظر خود را درون {} تعریف کنید. این عبارات جاوا اسکریپتی می تواند یک متغیر ریکتی باشد یا یک Property یا یک متد یا یک عبارت محاسباتی ریاضی.
بعنوان مثال در کد زیر می خواهیم حاصل جمع جبری 5+5 را در jsx تعریف کنیم:
const myelement = <h1>React is {5 + 5} times better with JSX</h1>;
تعریف بلاک کد طولانی از html:
برای تعریف کدهای html در چند خط متوالی در JSX باید از پرانتز به شکل زیر استفاده کرد:
const myelement = ( <ul> <li>Apples</li> <li>Bananas</li> <li>Cherries</li> </ul> );
نکته: دقت کنید که در اینگونه عبارات، باید حتما یک المان ریشه وجود داشته باشد. یعنی تمام المان های داخل کد HTML دارای یک والد باشند.
مثلا برای اینکه یک عبارت JSX معتبر و صحیح در ریکت تعریف کنیم نمی توان دو تگ H1 و H2 را به شکل زیر تعریف کرد:
const myelement = ( <h1>I am a Header.</h1> <h2>I am a Header too.</h2> );
بلکه باید آن دو تگ را داخل یک تگ والد (مثلا DIV) تعریف کنیم:
const myelement = ( <div> <h1>I am a Header.</h1> <h2>I am a Header too.</h2> </div> );
از آن جا که jsx از قواعد xml پیروی می کند، تمام تگ های html باید بسته شوند و مانند html5 نمی تواند تگی را باز رها کرد. بعنوان مثال:
const myelement = <input type="text" />;
کامپوننت های ریکت:
کامپوننت ها مانند توابع یا فانکشن عمل می کنند که یک المان html برمیگردانند.
کامپوننت به مجموعه ای از کدهای مستقل می گویند که قابلیت استفاده مجدد یا reusable دارند. همانند function ها در جاوا اسکریپت هستند با این تفاوت که خروجی آنها کد html می باشد.
کامپوننت ها در ری اکت به دو نوع کلی هستند: کلاس کامپوننت : class component و فانکشن کامپوننت: function component
تمرکز ما در این آموزش بر روی کلاس کامپوننت ها می باشد.
تعریف یک کلاس کامپوننت در ریکت:
برای ایجاد یک کامپوننت از نوع کلاس در ریکت، نام کامپوننت باید با حروف بزرگ (upper-case letter) آغاز شود.
پس از نام کامپوننت باید عبارت extends React.Component را تعریف کنیم. با استفاده از این عبارت کامپوننت شما از React.Component ارث بری می کند و می تواند از تمام توابع موجود در این کتابخانه استفاده کند.
متدی که حتما باید برای کلاس کامپوننت تعریف کنید render() نام دارد. خروجی این متد کد html است.
بعنوان مثال کلاس کامپوننت زیر را در نظر بگیرید:
class Car extends React.Component { render() { return <h2>Hi, I am a Car!</h2>; } }
اکنون اپلیکیشن ریکت شما یک کامپوننت دارد بنام Car که یک تگ <h2> برمی گرداند.
برای استفاده از کامپوننت Car کافیست آنرا بصورت تگ html و مطابق کد زیر فراخوانی کنید:
ReactDOM.render(<Car />, document.getElementById('root'));
قطعه کد فوق خروجی کامپوننت Car را در المان با آیدی root نمایش می دهد.
تعریف یک فانکشن کامپوننت در ریکت:
می خواهیم همان کامپوننت مثال فوق یعنی Car را توسط فانکشنال کامپوننت تعریف کنیم.
فانکشنال کامپوننت ها در ریکت همانند کلاس کامپوننت ها کار می کنند اما تفاوت هایی نیز باهم دارند. مثلا در کلاس کامپوننت متد render داریم اما در فانکشنال نداریم. در کلاس کامپوننت امکان استفاده از state را داریم اما در فانکشنال کامپوننت ها خیر.
کامپوننت Car بصورت فانکشنال:
function Car() { return <h2>Hi, I am also a Car!</h2>; }
همانطور که مشاهده می شود فانکشنال کامپوننت ها نیز باید با حروف بزرگ شروع شوند. همانند کلاس کامپوننت می توان آن را فراخوانی کرد:
ReactDOM.render(<Car />, document.getElementById('root'));
تعریف سازنده کامپوننت یا Constructor:
تعریف تابع سازنده یا constructor در کامپوننت های ریکت اجباری نیست اما اگر تعریف شود به محض اجرای کامپوننت ابتدا تابع سازنده فراخوانی می شود.
در ریکت معمولا property ها در آبجکتی بنام state تعریف می شوند که خود state نیز در داخل تابع سازنده قرار دارد.
در بخش های آینده درباره state بطور مفصل صحبت خواهیم کرد.
همچنین تابع سازنده یا constructor جایی است که باید از کامپوننت والد یا parent component ارث بری کنید. با استفاده از کلمه کلیدی super();
به مثال زیر دقت کنید:
class Car extends React.Component { constructor() { super(); this.state = {color: "red"}; } render() { return <h2>I am a Car!</h2>; } }
در کد فوق یک کامپوننت بنام Car تعریف کرده ایم که یک state بنام color دارد و مقدارش red است.
برای نمایش این مقدار در خروجی به شکل زیر عمل می کنیم:
class Car extends React.Component { constructor() { super(); this.state = {color: "red"}; } render() { return <h2>I am a {this.state.color} Car!</h2>; } }
مفهوم props در ریکت:
روش دیگری که می توان property های یک کامپوننت در ریکت را مدیریت کرد استفاده از props می باشد. در واقع props ها مانند آرگومان های توابع هستند و شما بعنوان اتریبیوت آنها را به کامپوننت ها ارسال می کنید.
در بخش بعدی بیشتر درباره props توضیح می دهیم.
به مثال زیر توجه کنید:
class Car extends React.Component { render() { return <h2>I am a {this.props.color} Car!</h2>; } } ReactDOM.render(<Car color="red"/>, document.getElementById('root'));
در مثال فوق یک props بنام color را به کامپوننت Car پاس داده ایم و آن را بصورت this.props.color در تابع رندر فراخوانی کرده ایم.
تعریف یک کامپوننت در کامپوننت دیگر:
می توان از کامپوننت های مختلف در یک کامپوننت استفاده کرد و آنها را صدا زد. به مثال زیر توجه کنید:
class Car extends React.Component { render() { return <h2>I am a Car!</h2>; } } class Garage extends React.Component { render() { return ( <div> <h1>Who lives in my Garage?</h1> <Car /> </div> ); } } ReactDOM.render(<Garage />, document.getElementById('root'));
در این مثال کامپوننت Car را در کامپوننت Garage فراخوانی کرده ایم.
تعریف کامپوننت در فایل:
ریکت بر اساس کامپوننت ها می باشد که شامل کدهایی هستند که می توان از آنها چندین بار و در چندین جای پروژه استفاده کرد. پس اگر کامپوننت ها را در فایل های مجزا تعریف کنیم کار هوشمندانه ای کرده ایم.
برای مثال یک فایل بنام Car.js ایجاد کنید و کدهای زیر را در آن تعریف کنید:
import React from 'react'; import ReactDOM from 'react-dom'; class Car extends React.Component { render() { return <h2>Hi, I am a Car!</h2>; } } export default Car;
همانطور که ملاحظه می کنید، ابتدا باید react و react-dom را در کامپوننت خود درون ریزی یا import کنیم. و در اخر فایل هم باید کامپوننت را export کنیم تا بتوانیم از سایر بخش های پروژه به آن دسترسی داشته باشیم.
هر جا که بخواهیم از کامپوننت Car استفاده کنیم باید آن را به شکل زیر تعریف کنیم:
import React from 'react'; import ReactDOM from 'react-dom'; import Car from './Car.js'; ReactDOM.render(<Car />, document.getElementById('root'));
آشنایی با props در ری اکت:
به آرگومان هایی که به کامپوننت های ریکت ارسال می شوند props می گویند. prop ها توسط صفات یا اتریبیوت های HTML به کامپوننت ها پاس داده می شوند.
پراپس ها در ریکت مانند آرگومان های توابع در جاوا اسکریپت و Attribute ها در HTML می باشند. به منظور ارسال props از کامپوننتی به کامپوننت دیگر فقط کافیست مانند تعریف صفات در HTML از آنها استفاده کنید.
مثال:
افزودن یک PROPS بعنوان Brand برای کامپوننت Car:
const myelement = <Car brand="Ford" />;
کامپوننت Car آرگومان brand را بصورت props دریافت خواهد کرد:
class Car extends React.Component { render() { return <h2>I am a {this.props.brand}!</h1>; } }
ارسال داده (Pass Data):
بنابراین برای ارسال یک یا چند آرگومان از کامپوننت A به کامپوننت B می توان از Props استفاده کرد.
در مثال زیر می خواهیم صفت brand را کامپوننت Garage به کامپوننت Car پاس بدهیم:
class Car extends React.Component { render() { return <h2>I am a {this.props.brand}!</h2>; } } class Garage extends React.Component { render() { return ( <div> <h1>Who lives in my garage?</h1> <Car brand="Ford" /> </div> ); } } ReactDOM.render(<Garage />, document.getElementById('root'));
در مثال بالا یک رشته یا string ثابت را بعنوان مقدار صفت brand به کاپوننت Car ارسال کرده ایم.
اما اگر بخواهیم یک متغییر را بصورت props به کامپوننت دیگر پاس دهیم باید آن متغیر را در براکت تعریف کنیم. مانند کد زیر:
class Car extends React.Component { render() { return <h2>I am a {this.props.brand}!</h2>; } } class Garage extends React.Component { render() { const carname = "Ford"; return ( <div> <h1>Who lives in my garage?</h1> <Car brand={carname} /> </div> ); } } ReactDOM.render(<Garage />, document.getElementById('root'));
حتی می توان یک شی یا object را بعنوان props به یک کاپوننت دیگر ارسال کرد. در مثال زیر آبجکت carinfo را برای صفت brand پاس داده ایم:
class Car extends React.Component { render() { return <h2>I am a {this.props.brand.model}!</h2>; } } class Garage extends React.Component { render() { const carinfo = {name: "Ford", model: "Mustang"}; return ( <div> <h1>Who lives in my garage?</h1> <Car brand={carinfo} /> </div> ); } } ReactDOM.render(<Garage />, document.getElementById('root'));
تعریف props در سازنده یا constructor:
اگر کامپوننت شما کلاس سازنده یا constructor دارد حتما باید props را به متد سازنده و همچنین به متد super() از کتابخانه React.Component ارسال کنید:
class Car extends React.Component { constructor(props) { super(props); } render() { return <h2>I am a Car!</h2>; } } ReactDOM.render(<Car model="Mustang"/>, document.getElementById('root'));
مفهوم state در ری اکت:
کامپوننت های ریکت یک آبجکت پیش فرض دارند بنام state. در واقع state جایی است که شما property های مربوط به یک کامپوننت را نگه داری می کنید.
به محض اینکه آبجکت state تغییر کند کامپوننت re-render خواهد شد.
تعریف یک شی state در reactjs:
آبجکت state را در سازنده کامپوننت تعریف کنید:
class Car extends React.Component { constructor(props) { super(props); this.state = {brand: "Ford"}; } render() { return ( <div> <h1>My Car</h1> </div> ); } }
نکته: آبجکت state میتواند تعداد نامحدودی property داشته باشد.
در مثال زیر 4 property برای state کامپوننت Car تعریف کرده ایم:
class Car extends React.Component { constructor(props) { super(props); this.state = { brand: "Ford", model: "Mustang", color: "red", year: 1964 }; } render() { return ( <div> <h1>My Car</h1> </div> ); } }
استفاده از state در ری اکت:
با استفاده از عبارت this.state.propertyname می تواند از هر جای کامپوننت به state دسترسی داشته باشید.
در مثال زیر به آبجکت state در متد رندر دسترسی پیدا می کنیم:
class Car extends React.Component { constructor(props) { super(props); this.state = { brand: "Ford", model: "Mustang", color: "red", year: 1964 }; } render() { return ( <div> <h1>My {this.state.brand}</h1> <p> It is a {this.state.color} {this.state.model} from {this.state.year}. </p> </div> ); } }
تغییر state در ری اکت:
برای تغییر مقدار state در کامپوننت های ریکت، از متد this.setState() استفاده کنید.
وقتی مقادیر state تغییر کند و آپددیت شوند، کامپوننت مربوطه re-render می شود و باعث می شود خروجی اپلیکیشن با توجه به مقدار جدید state بروز شود.
در مثال زیر یک دکمه تعریف کردیم که با کلیک روی آن مقدار color property تغییر می کند.
class Car extends React.Component { constructor(props) { super(props); this.state = { brand: "Ford", model: "Mustang", color: "red", year: 1964 }; } changeColor = () => { this.setState({color: "blue"}); } render() { return ( <div> <h1>My {this.state.brand}</h1> <p> It is a {this.state.color} {this.state.model} from {this.state.year}. </p> <button type="button" onClick={this.changeColor} >Change color</button> </div> ); } }
نکته مهم: همیشه سعی کنید از متد setState برای آپدیت کردن محتوای state ها در کامپوننت ریکت استفاده کنید. زیرا در اینصورت متد render بطور اتوماتیک فعال می شود و همچنین سایر متدهای مربوط به lifecycle ریکت.
تفاوت بین state و props در ری اکت:
در این بخش به بیان تفاوت های اساسی props و state خواهیم پرداخت:
- کامپوننت ها داده ها را از خارج از کامپوننت توسط props دریافت می کنند اما داده های داخلی خود را توسط state ایجاد و مدیریت می کنند.
- props ها برای ارسال داده بکار گرفته می شوند اما از state ها برای مدیریت داده ها و ذخیره آنها
- داده هایی که بصورت props ارسال می شوند توسط کامپوننت مقصد قابل ویرایش و آپدیت نمی باشند و فقط می توانند از آن استفاده کنند.
- مقادیر state ها را می توان درون خود کامپوننت تغییر داد و مدیریت کرد و از بیرون کامپوننت قابل تغییر نمی باشند.
- props ها فقط می توانند از کامپوننت والد یا parent به کامپوننت فرزند یا child ارسال شوند. یعنی ارسال داده بصورت یکطرفه است.
- تغییر state فقط با استفاده از متد setState ( ) امکان پذیر است.
چرخه حیات کامپوننت ها یا Lifecycle در ریکت:
هر کامپوننت در ریکت دارای چرخه حیات می باشد که می توانیم در سه فاز زیر آنها را مورد بررسی قرار دهیم:
Mount و Update و Unmount
فاز Mounting در ریکت:
در حالت Mounting المان ها در DOM درج می شوند. در فاز MOUNT شدن یک کامپوننت، ریکت 4 متد زیر را به ترتیب فراخوانی می کند:
constructor() getDerivedStateFromProps() render() componentDidMount()
متد render() یک متد اجباری است و تعریف آن در کامپوننت الزامی است و همیشه اجرا می شود. اما سایر متدهای فوق اختیاری هستند و در صورتی که توسط توسعه دهنده ریکت تعریف شوند اجرا خواهند شد.
متد سازنده در ریکت (Constructor):
متد سازنده در ریکت قبل از سایر متدهای کامپوننت اجرا می شود. به محض فراخوانی یک کامپوننت درری اکت، متد سازنده یا constructor صدا زده می شود. پس جای مناسبی است برای تعریف state های کامپوننتو مقداردهی اولیه سایر متغیرها.
متد سازنده معمولا با آرگومان ورودی props تعریف می شود و حتما باید اولین دستور آن super(props) باشد. متد super() متد سازنده خودش را صدا می کند و به کامپوننت جاری اجازه می دهد تا از متدهای والدش یعنی React.Component ارث بری کند.
متد سازنده هر بار که یک کامپوننت می سازید اجرا می شود. به مثال زیر دقت کنید:
class Header extends React.Component { constructor(props) { super(props); this.state = {favoritecolor: "red"}; } render() { return ( <h1>My Favorite Color is {this.state.favoritecolor}</h1> ); } } ReactDOM.render(<Header />, document.getElementById('root'));
متد getDerivedStateFromProps:
متد getDerivedStateFromProps درست قبل از رندر شدن المان ها در DOM اجرا می شود.
اینجا بطور طبیعی جایی است که می توان state را بر اساس props تنظیم کرد.
متد getDerivedStateFromProps آبجکت state را بصورت آرگومان ورودی می گیرد و state تغییر داده شده را بصورت خروجی بر میگرداند.
در مثال زیر ابتدا تعریف شده که مقدار state رنگ دلخواه برابر red باشد اما در متد getDerivedStateFromProps مقدار این state توسط اتریبیوت favcol تغییر یافته و به رنگ yellow آپدیت شده است.
class Header extends React.Component { constructor(props) { super(props); this.state = {favoritecolor: "red"}; } static getDerivedStateFromProps(props, state) { return {favoritecolor: props.favcol }; } render() { return ( <h1>My Favorite Color is {this.state.favoritecolor}</h1> ); } } ReactDOM.render(<Header favcol="yellow"/>, document.getElementById('root'));
متد render() در ریکت:
تعریف متد render() در کامپوننت های ری اکت ضروری و الزامی است. در واقع متد رندر خروجی HTML را به DOM میفرستد.
در مثال زیر یک کامپوننت ساده بهمراه یک متد رندر ساده نمایش داده شده است:
class Header extends React.Component { render() { return ( <h1>This is the content of the Header component</h1> ); } } ReactDOM.render(<Header />, document.getElementById('root'));
متد componentDidMount:
متد componentDidMount() پس از اینکه کامپوننت رندر شده اجرا می شود. دستوراتی را که نیاز است پس از RENDER شدن کامپوننت و نمایش آن در DOM اجرا شوند تعریف می شود.
در مثال زیر ابتدا رنگ مورد علاقه ما red تعریف شده است اما پس از رندر شدن و سپس اجرای DidMount مقدار آن به yellow تغییر یافته است.
class Header extends React.Component { constructor(props) { super(props); this.state = {favoritecolor: "red"}; } componentDidMount() { setTimeout(() => { this.setState({favoritecolor: "yellow"}) }, 1000) } render() { return ( <h1>My Favorite Color is {this.state.favoritecolor}</h1> ); } } ReactDOM.render(<Header />, document.getElementById('root'));
فاز Updating در ریکت:
پس از فاز اول چرخه حیات کامپوننت های ریکت یعنی Mounting، نوبت به فاز دوم لایف سایکل ریکت می رسد که پس از آپدیت شدن کامپوننت رخ می دهد.
یک کامپوننت ریکتی وقتی مقادیر state یا props در آن تغییر می کند بطور خودکار آپدیت می شود.
ریکت 5 متد داخلی دارد که پس از آپدیت شدن کامپوننت اجرا می شوند:
getDerivedStateFromProps() shouldComponentUpdate() render() getSnapshotBeforeUpdate() componentDidUpdate()
از بین این 5 متد، فقط متد render الزامی است و همیشه اجرا می شود. متدهای دیگر در صورتی که تعریف شوند اجرا خواهند شد.
متد getDerivedStateFromProps:
اولین متدی که پس از آپدیت شدن کامپوننت اجرا می شود متد getDerivedStateFromProps می باشد.
اینجا بطور طبیعی جایی است که می توان state را بر اساس props تنظیم کرد.
در مثال زیر داریم:
یک دکمه تعریف کرده ایم که با کلیک روی آن، مقدار رنگ مورد علاقه یا favorite color به blue تغییر می کند. اما از آنجاییکه متد getDerivedStateFromProps() فراخوانی شده و پس از آپدیت شدن کامپوننت اجرا می شود، از اتریبیوت favcol که مقدار yellow دارد استفاده می کند:
class Header extends React.Component { constructor(props) { super(props); this.state = {favoritecolor: "red"}; } static getDerivedStateFromProps(props, state) { return {favoritecolor: props.favcol }; } changeColor = () => { this.setState({favoritecolor: "blue"}); } render() { return ( <div> <h1>My Favorite Color is {this.state.favoritecolor}</h1> <button type="button" onClick={this.changeColor}>Change color</button> </div> ); } } ReactDOM.render(<Header favcol="yellow"/>, document.getElementById('root'));
متد shouldComponentUpdate:
در متد shouldComponentUpdateمی توانید یک خروجی بولین boolean برگردانید که تعیین می کند آیا ریکت باید به ادامه رندر کردن کامپوننت ادامه دهد یا خیر؟
مقدار پیش فرض true است.
در مثال زیر نشان دادیم که اگر مقدار خروجی متد فوق برابر false باشد چه اتفاقی می افتد. در واقع از رندر شدن کامپوننت پس از هر بار آپدیت جلوگیری کرده ایم:
class Header extends React.Component { constructor(props) { super(props); this.state = {favoritecolor: "red"}; } shouldComponentUpdate() { return false; } changeColor = () => { this.setState({favoritecolor: "blue"}); } render() { return ( <div> <h1>My Favorite Color is {this.state.favoritecolor}</h1> <button type="button" onClick={this.changeColor}>Change color</button> </div> ); } } ReactDOM.render(<Header />, document.getElementById('root'));
مثال زیر همانند مثال بالاست با این تفاوت که مقدار true را بعنوان خروجی برای متد shouldComponentUpdate() در نظر گرفته ایم:
class Header extends React.Component { constructor(props) { super(props); this.state = {favoritecolor: "red"}; } shouldComponentUpdate() { return true; } changeColor = () => { this.setState({favoritecolor: "blue"}); } render() { return ( <div> <h1>My Favorite Color is {this.state.favoritecolor}</h1> <button type="button" onClick={this.changeColor}>Change color</button> </div> ); } } ReactDOM.render(<Header />, document.getElementById('root'));
متد render:
وقتی کامپوننتی آپدیت می شود متد رندر مجددا اجرا خواهد شد. در واقع HTML را بصورت خروجی به DOM میفرستد و آنرا بروز رسانی می کند.
در مثال زیر یک دکمه داریم که مقدار رنگ مورد علاقه را به blue تغییر می دهد.
با فشردن دکمه مذکور، مقدار state برای favoritecolor از red به blue تغییر می یابد.
class Header extends React.Component { constructor(props) { super(props); this.state = {favoritecolor: "red"}; } changeColor = () => { this.setState({favoritecolor: "blue"}); } render() { return ( <div> <h1>My Favorite Color is {this.state.favoritecolor}</h1> <button type="button" onClick={this.changeColor}>Change color</button> </div> ); } } ReactDOM.render(<Header />, document.getElementById('root'));
متد getSnapshotBeforeUpdate:
توسط متد getSnapshotBeforeUpdate شما می توانید بفهمید state props قبل از آپدیت شدن کامپوننت چه مقادیری داشته اند.
دقت کنید که اگر متد getSnapshotBeforeUpdate() را در لایف سایکل کامپوننت خود تعریف کرده اید حتما باید متد componentDidUpdate() را نیز تعریف کنید وگرنه با خطا مواجه خواهید شد.
مثال پایین ممکن است پیچیده بنظر برسد اما کاری که در این مثال انجام می گیرد بصورت زیر است:
وقتی کامپوننت Header در فاز Mounting است با رنگ red رندر می شود. وقتیکه کامپوننت Mount شد، یک تایمر مقدار state را تغییر می دهد و پس از یک ثانیه مقدار favoritecolor برابر yellow می شود.
این اکشن فاز Update را فعال یا trigger می کند و بدلیل اینکه این کامپوننت دارای متد getSnapshotBeforeUpdate() هم می باشد، این متد اجرا می شود و پیغامی را در المان DIV1نمایش می دهد.
سپس متد componentDidUpdate() اجرا می شود و پیغامی را در DIV2 می نویسد.
بنابراین می توانید از متد getSnapshotBeforeUpdate() برای فهمیدن مقدار state قبل از آپدیت شدن بهره ببرید.
class Header extends React.Component { constructor(props) { super(props); this.state = {favoritecolor: "red"}; } componentDidMount() { setTimeout(() => { this.setState({favoritecolor: "yellow"}) }, 1000) } getSnapshotBeforeUpdate(prevProps, prevState) { document.getElementById("div1").innerHTML = "Before the update, the favorite was " + prevState.favoritecolor; } componentDidUpdate() { document.getElementById("div2").innerHTML = "The updated favorite is " + this.state.favoritecolor; } render() { return ( <div> <h1>My Favorite Color is {this.state.favoritecolor}</h1> <div id="div1"></div> <div id="div2"></div> </div> ); } } ReactDOM.render(<Header />, document.getElementById('root'));
متد componentDidUpdate:
متد componentDidUpdate وقتی اجرا می شود که کامپوننت در DOM آپدیت شده باشد.
مثالی که در بخش زیر آورده ایم ممکن است در نگاه اول پیچیده بنظر بیاید اما تمام کاری که انجام می دهد به صورت زیر است:
وقتی کامپوننت در حال Mounting است، مقدار favoritecolor برابر red می باشد. وقتی که کامپوننت Mount شد، یک تایمر state را تغییر می دهد و رنگ مورد علاقه را به yellow آپدیت می کند.
این اکشن باعث فعال شدن فاز Update می شود و از آنجائیکه این کامپوننت شامل متد componentDidUpdate می باشد، این متد اجرا می شود و پیغامی را در DIV می نویسد.
بنابراین متد componentDidUpdate وقتی فراخوانی می شود که آپدیت انجام شده باشد و DOM رندر شده باشد:
class Header extends React.Component { constructor(props) { super(props); this.state = {favoritecolor: "red"}; } componentDidMount() { setTimeout(() => { this.setState({favoritecolor: "yellow"}) }, 1000) } componentDidUpdate() { document.getElementById("mydiv").innerHTML = "The updated favorite is " + this.state.favoritecolor; } render() { return ( <div> <h1>My Favorite Color is {this.state.favoritecolor}</h1> <div id="mydiv"></div> </div> ); } } ReactDOM.render(<Header />, document.getElementById('root'));
فاز Unmounting:
فاز بعد از Mounting و Updating فاز Unmounting می باشد. در این مرحله، کامپوننت از DOM حذف می شود یا به بیان دیگر Unmount می شود.
ریکت فقط یک متد در فاز Unmount دارد بنام componentWillUnmount
متد componentWillUnmount():
متد componentWillUnmount زمانی اجرا می شود که کامپوننت ریکت در حال remove یا unmount شدن از DOM باشد.
در مثال زیر، با کلیک روی دکمه، هدر حذف خواهد شد:
class Container extends React.Component { constructor(props) { super(props); this.state = {show: true}; } delHeader = () => { this.setState({show: false}); } render() { let myheader; if (this.state.show) { myheader = <Child />; }; return ( <div> {myheader} <button type="button" onClick={this.delHeader}>Delete Header</button> </div> ); } } class Child extends React.Component { componentWillUnmount() { alert("The component named Header is about to be unmounted."); } render() { return ( <h1>Hello World!</h1> ); } } ReactDOM.render(<Container />, document.getElementById('root'));
رویدادها در ریکت (React Events):
درست مانند HTML ، ری اکت هم می تواند نسبت به رفتار کاربران در اپلیکیشن واکنش نشان دهد و رویداد خاصی را فراخوانی کند. REACTهم مانند HTML از رویدادهایی مانند Mouseover, change, click و … پشتیبانی می کند.
افزودن رویداد یا event در ری اکت:
نحوه تعریف ایونت ها در ریکت بصورت camel case می باشد. یعنی بجای onclick باید بنویسیم onClick
رویدادها در ری اکت درون براکت یا {} تعریف می شوند. در HTML رویدادها بصورت onclick=”myClick()” تعریف می شوند اما در ریکت بصورت onClick={myClick} می باشند.
رویداد onClick برای دکمه در ریکت:
<button onClick={shoot}>Take the Shot!</button>
رویداد onclick دکمه در html:
<button onclick="shoot()">Take the Shot!</button>
Event Handlers در ریکت:
روش مناسب برای استفاده از رویدادها در ریکت، تعریف کردن آنها بعنوان یک متد در کلاس کامپوننت می باشد.
در مثال زیر، تابع shoot را در کامپوننت Football تعریف کرده ایم:
class Football extends React.Component { shoot() { alert("Great Shot!"); } render() { return ( <button onClick={this.shoot}>Take the shot!</button> ); } } ReactDOM.render(<Football />, document.getElementById('root'));
استفاده از کلمه کلیدی this در ریکت:
در ری اکت، کلمه رزرو شده this به کامپوننتی اشاره می کند که متد موردنظر در آن قرار دارد. به همین دلیل است که باید از arrow function استفاده کنید. در arrow function ها کلمه this همیشه به آبجکتی اشاره می کند که تابع arrow در آن تعریف شده است.
مثال:
class Football extends React.Component { shoot = () => { alert(this); /* The 'this' keyword refers to the component object */ } render() { return ( <button onClick={this.shoot}>Take the shot!</button> ); } } ReactDOM.render(<Football />, document.getElementById('root'));
Arrow Function چیست و چرا باید از آن استفاده کرد؟
در کلاس کامپوننت های ریکت، کلمه کلیدی this بطور پیش فرض تعریف نشده است. بنابراین در توابع معمولی، کلمه this به آبجکتی اشاره دارد که متد در آن تعریف شده است. که می تواند آبجکت window یا دکمه html یا هر المان دیگری باشد.
» درباره کلمه کلیدی this در اکما اسکریپت 6 بیشتر بدانید.
اگر شما مجبورید از فانکشن های معمولی (regular functions) بجای فانکشن های arrow استفاده کنید، حتما باید مقدار this را توسط متد bind() برابر کامپوننت موردنظر قرار دهید.
مثال:
در کد زیر، از this در تابع shoot استفاده کردیم که در تابع سازنده آن را bind کردیم:
class Football extends React.Component { constructor(props) { super(props) this.shoot = this.shoot.bind(this) } shoot() { alert(this); /* Thanks to the binding in the constructor function, the 'this' keyword now refers to the component object */ } render() { return ( <button onClick={this.shoot}>Take the shot!</button> ); } } ReactDOM.render(<Football />, document.getElementById('root'));
نکته: بدون bind کردن کلمه this در متد constructor یا سازنده، کلمه this مقدار undefined برمیگرداند.
ارسال آرگومان به رویدادها در ریکت:
اگر شما می خواهید به event handler آرگومان ارسال کنید دو راه خواهید داشت:
1- مانند کد زیر یک anonymous arrow function ایجاد کنید:
در مثال زیر، با استفاده از arrow function، پارامتر Goal را به تابع shoot ارسال می کنیم:
class Football extends React.Component { shoot = (a) => { alert(a); } render() { return ( <button onClick={() => this.shoot("Goal")}>Take the shot!</button> ); } } ReactDOM.render(<Football />, document.getElementById('root'));
2- Bind کردن event handler به this:
دقت کنید که اولین آرگومان باید کلمه کلیدی this باشد. در مثال زیر Goalرا به شکل پارامتر به تابع shoot پاس داده ایم:
class Football extends React.Component { shoot(a) { alert(a); } render() { return ( <button onClick={this.shoot.bind(this, "Goal")}>Take the shot!</button> ); } } ReactDOM.render(<Football />, document.getElementById('root'));
نکته:
اگر شما آرگومان را بدون bind کردن ارسال کنید، یعنی عبارت this.shoot(this, “Goal”) را بجای this.shoot.bind(this, “Goal”) تعریف کنید، عملکرد کامپوننت بهم می ریزد. به اینصورت که تابع shoot پس از لود صفحه بطور اتوماتیک اجرا می شود. بجای اینکه با کلیک روی دکمه اجرا شود.
آبجکت رویداد در ریکت (React Event Object):
Event handlers به رویدادهای ریکت که تابع را فراخوانی می کند دسترسی دارند. در مثال زیر، رویداد مورد بررسی click می باشد.
توجه کنید که در صورت استفاده از arrow function ها ساختار کدنویسی متفاوت خواهد بود.
در توابع arrow شما باید بطور دستی آرگومان ایونت را ارسال کنید.
به قطعه کد زیر دقت کنید:
class Football extends React.Component { shoot = (a, b) => { alert(b.type); /* 'b' represents the React event that triggered the function, in this case the 'click' event */ } render() { return ( <button onClick={(ev) => this.shoot("Goal", ev)}>Take the shot!</button> ); } } ReactDOM.render(<Football />, document.getElementById('root'));
بدون استفاده از arrow function، آبجکت event بصورت خودکار بعنوان آخرین آرگومان در متد bind() ارسال می شود.
کد زیر را در این زمینه مشاهده کنید:
class Football extends React.Component { shoot = (a, b) => { alert(b.type); /* 'b' represents the React event that triggered the function, in this case the 'click' event */ } render() { return ( <button onClick={this.shoot.bind(this, "Goal")}>Take the shot!</button> ); } } ReactDOM.render(<Football />, document.getElementById('root'));
فرم های ریکت (ReactJS Forms):
درست مانند HTML ری اکت هم از فرم ها برای تعامل با کاربران در صفحات وب بهره می برد.
افزودن فرم در ریکت:
در مثال زیر فرمی ایجاد کردیم که کاربران می توانند نام خود را در آن وارد کنند:
class MyForm extends React.Component { render() { return ( <form> <h1>Hello</h1> <p>Enter your name:</p> <input type="text" /> </form> ); } } ReactDOM.render(<MyForm />, document.getElementById('root'));
مدیریت فرم (Handling Forms):
به این معنیست که چگونه داده های دریافتی از فرم یا تغییر داده شده را مدیریت کنیم. در HTML داده های فرم معمولا توسط DOM مدیریت می شوند. اما در ریکت داده های فرم توسط کامپوننت ها مدیریت می شوند. در این حالت تمام داده ها در state ذخیره می شوند. می توان با تعریف یک event handler در اتریبیوت onChange تغییرات را کنترل کنید.
مثال: در کد زیر یک event handler تعریف کردیم که می تواند آبجکت state را آپدیت کند.
class MyForm extends React.Component { constructor(props) { super(props); this.state = { username: '' }; } myChangeHandler = (event) => { this.setState({username: event.target.value}); } render() { return ( <form> <h1>Hello {this.state.username}</h1> <p>Enter your name:</p> <input type='text' onChange={this.myChangeHandler} /> </form> ); } } ReactDOM.render(<MyForm />, document.getElementById('root'));
نکته 1: باید قبل از اینکه بتوانید از state استفاده کنید آن را در متد سازنده مقداردهی اولیه یا initialize کنید.
نکته 2: می توان با تعریف دستور event.target.value به مقدار فیلد موردنظر دسترسی داشته باشید.
رندر کردن شرطی (Conditional Rendering):
برای مثال اگر می خواهید تا وقتی که کاربر یک مقداری بعنوان ورودی یا input در فرم وارد نکرده تگ h1 به او نمایش داده نشود، می توانید براحتی از دستور شرطی if استفاده کنید.
در مثال زیر به این نکات توجه کنید:
- یک متغیر خالی بنام header تعریف کرده ایم.
- اگر کاربر مقداری در input وارد کرد متغیر header با محتوای دلخواه پر می شود.
- توسط {header} مقدار متغیر هدر را در خروجی نمایش داده ایم.
class MyForm extends React.Component { constructor(props) { super(props); this.state = { username: '' }; } myChangeHandler = (event) => { this.setState({username: event.target.value}); } render() { let header = ''; if (this.state.username) { header = <h1>Hello {this.state.username}</h1>; } else { header = ''; } return ( <form> {header} <p>Enter your name:</p> <input type='text' onChange={this.myChangeHandler} /> </form> ); } } ReactDOM.render(<MyForm />, document.getElementById('root'));
ثبت فرم (Submitting Form):
می توان اکشن ثبت فرم را با تعریف یک event handler برای اتریبیون onSubmit کنترل کنید.
class MyForm extends React.Component { constructor(props) { super(props); this.state = { username: '' }; } mySubmitHandler = (event) => { event.preventDefault(); alert("You are submitting " + this.state.username); } myChangeHandler = (event) => { this.setState({username: event.target.value}); } render() { return ( <form onSubmit={this.mySubmitHandler}> <h1>Hello {this.state.username}</h1> <p>Enter your name, and submit:</p> <input type='text' onChange={this.myChangeHandler} /> <input type='submit' /> </form> ); } } ReactDOM.render(<MyForm />, document.getElementById('root'));
چند فیلد input در فرم:
در صورت داشتن چندین فیلد input در فرم، می توان با تعریف اتریبیوت name هریک از آنها را کنترل کرد.
وقتی می خواهید state را در متد سازنده کلاس مقداردهی اولیه کنید، از اتریبیوت name فیلدها استفاده کنید.
برای دسترسی به مقادیر فیلدهای input در event handler از دستور event.target.name و event.target.value استفاده کنید.
به منظور آپدیت کردن state توسط ساختار setState، مقادیر فوق را در براکت [] تعریف کنید.
مثالی با 2 فیلد input:
class MyForm extends React.Component { constructor(props) { super(props); this.state = { username: '', age: null, }; } myChangeHandler = (event) => { let nam = event.target.name; let val = event.target.value; this.setState({[nam]: val}); } render() { return ( <form> <h1>Hello {this.state.username} {this.state.age}</h1> <p>Enter your name:</p> <input type='text' name='username' onChange={this.myChangeHandler} /> <p>Enter your age:</p> <input type='text' name='age' onChange={this.myChangeHandler} /> </form> ); } } ReactDOM.render(<MyForm />, document.getElementById('root'));
اعتبارسنجی فیلدهای فرم (Validating Form Input):
شما می توان در حین اینکه کاربر در حال تایپ کردن در input های فرم است اعتبارسنجی را انجام دهید و هم می توانید وقتی فرم را ثبت کرد عملیات اعتبارسنجی را انجام دهید.
در مثال زیر وقتی فیلد age را پر می کنید اگر ورودی بصورت عددی نباشد پیغام خطا می دهد:
class MyForm extends React.Component { constructor(props) { super(props); this.state = { username: '', age: null, }; } myChangeHandler = (event) => { let nam = event.target.name; let val = event.target.value; if (nam === "age") { if (!Number(val)) { alert("Your age must be a number"); } } this.setState({[nam]: val}); } render() { return ( <form> <h1>Hello {this.state.username} {this.state.age}</h1> <p>Enter your name:</p> <input type='text' name='username' onChange={this.myChangeHandler} /> <p>Enter your age:</p> <input type='text' name='age' onChange={this.myChangeHandler} /> </form> ); } } ReactDOM.render(<MyForm />, document.getElementById('root'));
در مثال زیر همان کار اعتبارسنجی مثال بالا را انجام می دهیم با این تفاوت که پس از ثبت فرم توسط کاربر، کار اعتبارسنجی یا validation انجام شده و پیغام مناسب به کاربر نمایش داده می شود:
class MyForm extends React.Component { constructor(props) { super(props); this.state = { username: '', age: null, }; } mySubmitHandler = (event) => { event.preventDefault(); let age = this.state.age; if (!Number(age)) { alert("Your age must be a number"); } } myChangeHandler = (event) => { let nam = event.target.name; let val = event.target.value; this.setState({[nam]: val}); } render() { return ( <form onSubmit={this.mySubmitHandler}> <h1>Hello {this.state.username} {this.state.age}</h1> <p>Enter your name:</p> <input type='text' name='username' onChange={this.myChangeHandler} /> <p>Enter your age:</p> <input type='text' name='age' onChange={this.myChangeHandler} /> <br/> <br/> <input type='submit' /> </form> ); } } ReactDOM.render(<MyForm />, document.getElementById('root'));
افزودن پیغام خطا (Error Message):
نمایش پیغام خطا در باکس alert می تواند برای کاربر آزاردهنده باشد. پس بهتر است یک error msg در state تعریف کنیم و به محض اینکه کاربر مقداری نادرست را در input وارد کرد این پیغام خطا را به او نمایش دهیم:
class MyForm extends React.Component { constructor(props) { super(props); this.state = { username: '', age: null, errormessage: '' }; } myChangeHandler = (event) => { let nam = event.target.name; let val = event.target.value; let err = ''; if (nam === "age") { if (val !="" && !Number(val)) { err = <strong>Your age must be a number</strong>; } } this.setState({errormessage: err}); this.setState({[nam]: val}); } render() { return ( <form> <h1>Hello {this.state.username} {this.state.age}</h1> <p>Enter your name:</p> <input type='text' name='username' onChange={this.myChangeHandler} /> <p>Enter your age:</p> <input type='text' name='age' onChange={this.myChangeHandler} /> {this.state.errormessage} </form> ); } } ReactDOM.render(<MyForm />, document.getElementById('root'));
Textarea:
المنت textarea در ریکت کمی با HTML متفاوت است. در HTML مقدار Textarea داخل تگ باز <textarea> و تگ بسته </textarea> تعریف می شود اما در ReactJS مقدار این المنت در اتریبیوت value قرار می گیرد:
در مثال زیر یک فیلد textarea داریم که مقدارش در متد سازنده با یک محتوای تستی پر می شود:
class MyForm extends React.Component { constructor(props) { super(props); this.state = { description: 'The content of a textarea goes in the value attribute' }; } render() { return ( <form> <textarea value={this.state.description} /> </form> ); } } ReactDOM.render(<MyForm />, document.getElementById('root'));
Select:
فیلد کمبوباکس یا dropdown یا select در ReactJS کمی نسبت به HTML متفاوت است. در HTML گزینه انتخابی کاربر با اتریبیوت selected تعریف می شود:
<select> <option value="Ford">Ford</option> <option value="Volvo" selected>Volvo</option> <option value="Fiat">Fiat</option> </select>
اما در ری اکت، آیتم انتخابی درون اتریبیوت value در تگ select قرار می گیرد:
class MyForm extends React.Component { constructor(props) { super(props); this.state = { mycar: 'Volvo' }; } render() { return ( <form> <select value={this.state.mycar}> <option value="Ford">Ford</option> <option value="Volvo">Volvo</option> <option value="Fiat">Fiat</option> </select> </form> ); } } ReactDOM.render(<MyForm />, document.getElementById('root'));
استایل دهی به ریکت توسط CSS:
از روش های گوناگونی می توان به اپلیکیشن های ری اکت استایل داد. ما در این مقاله به بیان دو روش استایل دهی درون خطی (inline) و فایل css می پردازیم.
روش اول: استایل دهی درون خطی (Inline Styling):
به منظور استایل دادن به المان های صفحه بصورت inline باید از آبجکت جاوا اسکریپتی استفاده کرد:
class MyHeader extends React.Component { render() { return ( <div> <h1 style={{color: "red"}}>Hello Style!</h1> <p>Add a little style!</p> </div> ); } }
نکته: در JSX از آکولاد {} برای تعریف دستورات استفاده می شود. علاوه بر این آبجکت ها در جاوا اسکریپت نیز شامل آکولاد هستند. پس در تعریف استایل style={{color: “red”}} از دو آکولاد استفاده شده است.
تعریف نام property بصورت camelCase:
از آنجا که استایل های درون خطی css در ریکت باید در آبجکت های جاوااسکریپتی تعریف شوند، اگر استایل موردنظر دو یا چندبخشی باشد باید بصورت camelCase تعریف شود. مثلا بجای background-color باید بنویسیم backgroundColor:
class MyHeader extends React.Component { render() { return ( <div> <h1 style={{backgroundColor: "lightblue"}}>Hello Style!</h1> <p>Add a little style!</p> </div> ); } }
آبجکت جاوا اسکریپتی (Javascript Objects):
شما همچنین می توانید استایل های موردنظر خود را در یک آبجکت جاوا اسکریپتی تعریف کنید و آن را در اتریبیوت style درج کنید:
class MyHeader extends React.Component { render() { const mystyle = { color: "white", backgroundColor: "DodgerBlue", padding: "10px", fontFamily: "Arial" }; return ( <div> <h1 style={mystyle}>Hello Style!</h1> <p>Add a little style!</p> </div> ); } }
روش دوم: فایل استایل شیت CSS:
روش دیگر برای تعریف استایل اینست که آنها را در یک فایل css مجزا تعریف کنید. فقط کافیست آن را با فرمت .css تعریف کرده و در اپلیکیشن خود import کنید. در مثال زیر استایل موردنظر را در فایل App.css درج می کنیم:
app.css
body { background-color: #282c34; color: white; padding: 40px; font-family: Arial; text-align: center; }
نام فایل css دلخواه است اما فرمتش باید css باشد. الان باید در فایل index.js آن را import کنید:
index.js
import React from 'react'; import ReactDOM from 'react-dom'; import './App.css'; class MyHeader extends React.Component { render() { return ( <div> <h1>Hello Style!</h1> <p>Add a little style!.</p> </div> ); } } ReactDOM.render(<MyHeader />, document.getElementById('root'));
ماژول های CSS:
راه دیگر برای اعمال استایل های CSS در اپلیکیشن های ری اکت، استفاده از ماژول های CSS می باشد. این روش بخصوص برای وقتیکه کامپوننت های برنامه در فایل های مجزا تعریف شده اند کاربرد دارد.
نکته: استایلی که در فایل module تعریف شده فقط در همان کامپوننتی که آن را import می کند قابل شناسایی و دسترسی است.
فرمت فایل های ماژول .module.css است. در مثال زیر فایل mystyle.module.css را ایجاد کردیم و استایل های موردنظر را در آن تعریف کردیم:
mystyle.module.css
.bigblue { color: DodgerBlue; padding: 40px; font-family: Arial; text-align: center; }
استایل شیت فوق را در فایل App.js ایمپورت کنید:
app.js
import React from 'react'; import ReactDOM from 'react-dom'; import styles from './mystyle.module.css'; class Car extends React.Component { render() { return <h1 className={styles.bigblue}>Hello Car!</h1>; } } export default Car;
حالا کامپوننت فوق را باید در اپلیکیشن import کنیم:
index.js
import React from 'react'; import ReactDOM from 'react-dom'; import Car from './App.js'; ReactDOM.render(<Car />, document.getElementById('root'));
استفاده از SASS در CSS:
» Sass چیست؟ پیش پردازنده یا Pre-Processor برای CSS است. فایل های SASS روی سرور اجرا می شوند و استایل های CSS را به مرورگر ارسال می کنند.
» چطور می توان از SASS در پروژه های ریکتی استفاده کرد؟ اگر اپلیکیشن ریکت خود را با دستور create-react-app ایجاد کرده باشید براحتی می توانید با اجرای فرمان زیر در cmd امکان تعریف فایل sass را فراهم کنید:
C:\Users\Your Name>npm install node-sass
ایجاد فایل SASS:
نحوه ایجاد فایل های sass شبیه css است با این تفاوت که پسوند فایل های Sass ، scss است.
در فایل sass می توان از متغیرها و توابع استفاده کرد. در کد زیر در فایل mysass.scss یک متغیر تعریف کرده ایم و آن را در تگ h1 استفاده کرده ایم:
mysass.scss
$myColor: red; h1 { color: $myColor; }
اکنون باید آن را در فایل index.js ایمپورت کنیم:
index.js
import React from 'react'; import ReactDOM from 'react-dom'; import './mysass.scss'; class MyHeader extends React.Component { render() { return ( <div> <h1>Hello Style!</h1> <p>Add a little style!.</p> </div> ); } } ReactDOM.render(<MyHeader />, document.getElementById('root'));
مقاله آموزش مقدماتی ری اکت در اینجا به پایان می رسد. از شما کاربران گرامی خواهشمندم سوالات و دیدگاه های خود را با ما در میان بگذارید.
دیدگاهتان را بنویسید