پرش به مطلب اصلی

JSX & Component & Props

jsx چیست؟

jsx مخفف JavaScript XML که این قابلیت را به ما میده وسط کد های ریکتمون html بنویسم که قابلیت خیلی جذابی هست که عاشقش میشید

برای مثال ما میتونیم درون یک متغیر یک تگ html قرار بدیم

const myElement = <h1>I Love JSX!</h1>;

که در نهایت میتیم این تگ را بدیم به ریکت برامون توی صفحه رندرش کنه

const myElement = <h1>I Love JSX!</h1>;

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(myElement);

البته استفاده از jsx اجباری نیست و میتونیم با خود ریکت تگهامون بسازیم که کار بسیار سخت و کد ها کثیف میشه

const myElement = React.createElement('h1', {}, 'I do not use JSX!');

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(myElement);

قواعد JSX

متغییرها

ما میتونیم وسط jsx عبارات جاوااسکریپی بنویسیم

const myElement = <h1>React is {5 + 5} times better with JSX</h1>;

const firstName = "Gholamreza";
const lastName = "Fadakar";
const MyElement2 = <h1>Fullname: {firstName} {lastName}</h1>

const age = 28;
const MyElement3 = <h1>Is Old: {(age) > 50 ? "Yes" : "No"}</h1>

نکته

درون jsx حتما باید تمامی تگ ها بسته بشه وگرنه کامپایلر به ما خطا میده

const tagWithChid = <h1>my title</h1>
const tagWithoutChild = <br />

تگ های تو در تو

اگر چدین تگ تو در در تو داشته باشیم باید حتما ان را درون () قرار دهیم

const myList = (
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
);

شرط

چطور در jsx شرط بذاریم ؟ چند راه وجود داره که میتونیم اول به این مورد اشاره کنیم:

const list = [1,2,3,4,5];

const renderItems = () => {
return list.map((item) => item < 4 ? <li>Item {item}</li> : undefined);
};

const myList = (
<ul>
{renderItems()}
</ul>
);

به مثال بالا دقت کنید رندر کردن ایتم های لیست درون یک تابع قرارگرفته که با شرط محدود شده در نهایت ارایه ای از jsx ها برگردادنده شده.

حالت بعدی میتوان در درون jsx این عمل را انجام داد:

const age = 28;

const jsx = (
<div>
{age > 50 ? <h2>Old</h2> : <h2>young</h2>}
</div>
);
نکته

در مثال بالا با عملگر ؟ : شرط در رندر اعمال شده.

حالت بعدی رندر یا عدم رندر یک تگ در jsx است به مثال پایین دقت کنید:

const renderHeader = false;

const jsx = (
<div>
{renderHeader && <h1>my header</h1> }
</div>
);

در صورت درست بودن عبارت دستورات بعد از && اجرا میشود در غیر این صورت هیچ رندری اتفاق نمیافتد

حلقه

برا نمایش لیستی از داده ها در jsx میتوانیم انها را map کنیم

const list = [1,2,3,4,5];

const myList = (
<ul>
{list.map((item) => {
return <li>{item}</li>
})}
</ul>
);

به این نکته دقت کنید که ما میتنوانیم یک المان jsx برگردانیم یا یک ارایه ای از المان های jsx که در این صورت هر دو رندر خواهند شد

حالا که با jsx آشنا شدیم میتونیم راحت تر با ریکت المان های صفحه را بسازیم


کامپوننت چیست ؟

کامپونت ها در دورن ریکت چی هست ؟

کامپونت ها در ریکت همون function های ما هستن که یک خروجی jsx دارن که در نهایت درون صفحه با صدا کردنشون رندر میشن و قابلیت مهمی که کامپونت ها دارن اینه که میشه چندین بار در جاهای مختلف صداشون کرد و از خروجی jsx انها استفاده کرد

چقدر جالبه !

همین الان توی ذهت میاد که خیلی چیزای دردساز را میشه کامپونتت کرد مثل دکمه ها - لیست ها - جدول ها - سر عنوان ها و خیلی چیزای دیگه

خب اینکار مزیت هایی برای ما داره فرض کنید من یک کامپونت جدول ایجاد کردن که داخل پروژه من استفاده شده و از اون بالای ۵۰ بار استفاده کردم که خیلی لذت بخش بوده چون دیگه هر سری جدول رو ننوشتم حالا میخوام یه تغییری داخل جدول های پروژم بدم که حالت واکنشگرا بگیرن کافیه فقط کامپوننتش را تغییر بدم تا همه جا تغییر کنه و این خیلی مهمه که ما به راحتی بتونیم قسمتی از پرژه بدون دردسر ریفکتور کنیم

اگر کامپوننت نبود چی؟ باید ۵۰ بار ویرایش میزدیم و خسته کننده میشود و از همه مهمتر ممکن بود یکیشون ناقص ریفکتور کنیم.

پس از ریکت ممنونیم که کامپوننت ها رو برای ما گذاشته.

ساخت کامپوننت در ریکت

برای ساخت کامپونتت یک پوشه در src ایجاد میکنیم به اسم components که بتونیم اون ها را بسته بندی کنیم و با بقیه فایل ها قاطی نشن

یک فایل به اسم Button.js درون فولدر component میسازیم

const Button = () => {
return (
<button>salam</button>
);
}

export default Button

همونطور که گفتیم کامپوننت ها فاکنکشن هایی هستن که jsx خروجی برمیگردون

حالا میتونیم این کامپوننت را درون App.js صدا بزنیم

import Button from './Button';

function App() {
return (
<div className="App">
<Button />
</div>
);
}

export default App;

همانطور که میبینید دکمه برای ما نمایش داده میشه

نکته هایی اینجا هست که لازمه بدونید

  • برای صدا کردن کامپوننتون باید دقیقا اسم فانکشن را به صورت تگ html بنویسیم
  • حتما باید اسم کامپونتمون با حرف بزرگ شروع بشه
  • در اینجا چون کامپوننت فرزندی نداره پس تگش بدون تگ پایانی بسته شده
  • میشود همانند کامپوننت App از فاکنشن معمولی به جای arrow استفاده کرد
  • به علت استفاده ریکت از virtual dom تگ هیچ کدام از کامپونتت های ما درون dom نمایش داده نخواهد شد

ارسال داده به کامپوننت

قطعا کامپونتت هایی که میسازیم ثابت نیستن و بر اساس داده هایی رندر میشن

چطور میتونیم به کامپوننت ها داده ارسال کنیم ؟

برای این کار ما میتونیم به روش زیر داده ای را برای کامپوننت ارسال کنیم فرض کنید متن دکمه را میخوام از جایی که صدا میزنیم بهش بدیم

import Button from './Button';

function App() {
return (
<div className="App">
<Button content="Hello World !" />
</div>
);
}

export default App;

یک attribute تعریف میکنیم به اسم content و یک متن بهش میدیم تا برامون ارسالش کنه به کامپوننت دکمه و از درون کامپوننت دکمه اون را دریافت کنیم

const Button = (props) => {
return (
<button>{props.content}</button>
);
}

export default Button

props تمامی داده های ما هستن که از بیرون امدن و به صورت object
درون props قرار گرفتن پس ما میتونیم با صدا کردن props.content اونو دریافت کنیم و نمایش بدیم

البته حرفه ای تر این هست که props را همونجا destruct کنیم و فقط content رو برداریم به صورت زیر:

const Button = ({ content }) => {
return (
<button>{content}</button>
);
}

export default Button

حالا اگر متن ما درون یک متغییر بود و بخواهیم به دکمه ارسالش کنیم چی ؟ طبق قوانین jsx میتونیم به صورت زیر عمل کنیم

import Button from './Button';

function App() {

const myButtonText = "Hello World !"

return (
<div className="App">
<Button content={myButtonText} />
</div>
);
}

export default App;

ارسال jsx به کامپونت

یک props از قبل تعریف شده ای درون ریکت هاست که در صورت باز کردن تک کامپونت برای ما پرش میکنه به مثال زیر دقت کنید

<Button> Hello World ! </Button>

این محتوایی jsx که ما بین تگ ها قرار میگیره ریکت برامون درون children قرار میده که میتونیم درون کامپونت ازش استفاده کنیم

const Button = ({ children }) => {
return (
<button>{children}</button>
);
}

export default Button

از اونجایی که children داره توسط محتوای وسط تگ Button پر میشه پس باید توقع داشته باشیم jsx باشه

<Button>
Hello World !
<i className="fa fa-rocket"></i>
</Button>

نکته ای اینجا وجود داره این هست که attribute تگ i از جنس class نیست و className هست درون ریکت به جای استفاده از class از className باید استفاده کنیم


پروژه

پیاده سازی کامپوننت های پروژه وینترین و صفحه ساز