شروع سریع با React

به مستندات React خوش آمدید! این صفحه به شما مقدمهای مشتمل بر 80٪ از مفاهیم React که به صورت روزانه از آن استفاده خواهید کرد، را ارائه میدهد.
تعریف و استفاده تو در تو از کامپوننتها
برنامههای React از کامپوننتها تشکیل شدهاند. یک کامپوننت بخشی از UI (رابط کاربری) است که منطق و ظاهر خاص خود را دارد. یک کامپوننت میتواند به کوچکترین اندازه یک دکمه یا به اندازه یک صفحه کامل باشد.
کامپوننتهای React توابع JavaScript هستند که یک مقدار مارکاپ برمیگردانند:
function MyButton() {
return (
<button>من یک دکمه هستم</button>
);
}
حالا که شما MyButton
را تعریف کردهاید، میتوانید آن را درون یک کامپوننت دیگر به صورت تو در تو استفاده کنید:
export default function MyApp() {
return (
<div>
<h1>به برنامه من خوش آمدید</h1>
<MyButton />
</div>
);
}
توجه داشته باشید که نام با حرف بزرگ شروع میشود. این نشانه کامپوننت React بودن المان است. نام کامپوننتهای React باید همیشه با حرف بزرگ شروع شوند، در حالی که تگهای HTML باید به صورت کوچک نوشته شوند.
function MyButton() {
return (
<button>
من یک دکمه هستم
</button>
);
}
export default function MyApp() {
return (
<div>
<h1>به برنامه من خوش آمدید</h1>
<MyButton />
</div>
);
}
عبارت export default
کامپوننت اصلی در فایل را برای اکسپورت مشخص میکند. اگر با برخی از سینتکسهای JavaScript آشنا نیستید، MDN و javascript.info منابع خوبی برای یادگیری آنها هستند.
نشانهگذاری با JSX
سینتکس مارکاپ که در بالا دیدید JSX نامیده میشود. استفاده از آن اختیاری است، اما بیشتر پروژههای React از JSX به دلیل راحتی توسعه استفاده میکنند. تمام ابزارهایی که برای توسعه توصیه میکنیمبه طور پیشفرض از JSX پشتیبانی میکنند.
JSX سختگیرتر از HTML است. شما باید تگها را مانند ببندید. کامپوننت شما همچنین نمیتواند چندین تگ JSX را برگرداند. شما باید آنها را در یک والد مشترک، مانند
...
یا یک المان خالی ...
قرار دهید:
function AboutPage() {
return (
<>
<h1>درباره</h1>
<p>سلام.<br />حال شما چطور است؟</p>
</>
);
}
اگر HTML زیادی دارید که باید به JSX منتقل شود، میتوانید از یک تبدیلگر آنلاین استفاده کنید.
اضافه کردن استایلها
در React، شما یک کلاس CSS را با className
مشخص میکنید. همانند ویژگی class
در HTML:
<img className="avatar" />
و قوانین CSS مورد نظر را می توانید در یک فایل CSS جدا بنویسید:
/* در CSS شما */
.avatar {
border-radius: 50%;
}
React نحوه اضافه کردن فایلهای CSS را مشخص نمی کند. در سادهترین حالت، شما یک تگ می توانید به HTML خود اضافه میکنید. اگر از یک ابزار ساخت یا یک فریمورک مانند WebPack استفاده میکنید، می توانید با مطالعه مستندات آن نحوه افزودن فایل CSS به پروژه خود را یادبگیرید.
نمایش دادهها
سینتکس JSX به شما اجازه میدهد تا مارکاپ را به کدهای JavaScript وارد کنید. آکولادها به شما اجازه میدهند تا در میان مارکاپ دوباره به JavaScript برگردید تا بتوانید برخی متغیرها را از کد خود در بین مارکاپ استفاده کنید و مقدار آنها را به کاربر نمایش دهید. به عنوان مثال، کد زیر مقدار user.name
را نمایش میدهد:
return (
<h1>
{user.name}
</h1>
);
شما همچنین میتوانید در اتریبیوت های JSX از "JavaScript" استفاده کنید، اما باید از آکولاد به جای کوتیشن استفاده کنید. به عنوان مثال، className="avatar"
رشته "avatar"
را به عنوان کلاس CSS مشخص می کند، اما src={user.imageUrl}
مقدار متغیر JavaScript user.imageUrl
را خوانده و سپس مقدارش را به عنوان ویژگی src
تعیین می کند:
return (
<img
className="avatar"
src={user.imageUrl}
/>
);
شما میتوانید عبارات پیچیده را نیز داخل آکولادهای JSX قرار دهید، به عنوان مثال، ادغام رشتهها:
مشاهده کد و اجرای آن در CodeSandbox
const user = {
name: 'هدی لامار',
imageUrl: 'https://i.imgur.com/yXOvdOSs.jpg',
imageSize: 90,
};
export default function Profile() {
return (
<>
<h1>{user.name}</h1>
<img
className="avatar"
src={user.imageUrl}
alt={'عکس ' + user.name}
style={{
width: user.imageSize,
height: user.imageSize
}}
/>
</>
);
}
در مثال بالا، دستور style={{}}
یک سینتکس خاص نیست، بلکه یک شی عادی جاوااسکریپت است که داخل آکولادهای JSX style={ }
قرار گرفته است. شما میتوانید از ویژگی style
زمانی که استایلهای شما با استفاده از مقادیر متغیرها تعیین می شوند، استفاده کنید.
رندر کردن شروط
در React، سینتکس خاصی برای نوشتن شروط وجود ندارد. در عوض، شما از همان دستورات JavaScript معمولی استفاده میکنید. به عنوان مثال، میتوانید از یک دستور برای بازگرداندن مارکاپ به صورت شرطی استفاده کنید:
let content;
if (isLoggedIn) {
content = <AdminPanel />;
} else {
content = <LoginForm />;
}
return (
<div>
{content}
</div>
);
اگر کد جمع و جورتر را ترجیح میدهید، میتوانید از عملگر شرطی استفاده کنید. این عملگر برخلاف if
، درون مارکاپ JSX نیز کار میکند:
<div>
{isLoggedIn ? (
<AdminPanel />
) : (
<LoginForm />
)}
</div>
زمانی که به else
نیاز ندارید، میتوانید از سینتکس منطقی نیز برای کوتاه تر کردن کد استفاده کنید:
<div>
{isLoggedIn && <AdminPanel />}
</div>
تمام این روشها همچنین برای مشخص کردن شرطی ویژگیها کار میکنند. اگر با برخی از این سینتکسهای JavaScript آشنا نیستید، میتوانید با استفاده از if...else
شروع کنید.
رندر کردن لیستها
برای رندر لیستها، به فیچرهای JavaScript مانند حلقه و تابع احتیاج دارید.
به عنوان مثال، فرض کنید شما آرایهای از محصولات دارید:
const products = [
{ title: 'کلم', id: 1 },
{ title: 'سیر', id: 2 },
{ title: 'سیب', id: 3 },
];
درون کامپوننت خود، از تابع map()
برای تبدیل یک آرایه از محصولات به آرایهای از آیتمهای استفاده کنید:
const listItems = products.map(product =>
<li key={product.id}>
{product.title}
</li>
);
return (
<ul>{listItems}</ul>
);
توجه داشته باشید که دارای ویژگی ای به نام
key
است. برای هر آیتم در لیست، باید یک رشته یا عدد که به طور منحصر به فرد آن آیتم را در بین خواهر و برادرهایش شناسایی میکند، ارائه دهید. معمولاً کلید باید از دادههای شما، مانند شناسه پایگاه داده، بیاید. React از کلیدها برای دانستن اینکه بعداً چه اتفاقی میافتد، استفاده میکند، برای مثال اگر شما آیتمهای جدید را وارد، حذف یا دوباره مرتب کنید، ری اکت بوسیله کلیدها تصمیم به بروز کردن المان مرتبط با آن دیتا می گیرد.
const products = [
{ title: 'کلم', isFruit: false, id: 1 },
{ title: 'سیر', isFruit: false, id: 2 },
{ title: 'سیب', isFruit: true, id: 3 },
];
export default function ShoppingList() {
const listItems = products.map(product =>
<li
key={product.id}
style={{
color: product.isFruit ? 'magenta' : 'darkgreen'
}}
>
{product.title}
</li>
);
return (
<ul>{listItems}</ul>
);
}
پاسخ به رویدادها
شما میتوانید به رویدادها با تعیین تابع مدیریت رویداد درون کامپوننت پاسخ دهید:
function MyButton() {
function handleClick() {
alert('شما روی من کلیک کردید!');
}
return (
<button onClick={handleClick}>
روی من کلیک کنید
</button>
);
}
توجه داشته باشید که onClick={handleClick}
در انتها هیچ پرانتزی ندارد! با استفاده از پرانتز، شما تابع مدیریت رویداد را فراخوانی کرده اید: برای همین فقط باید نام آن را به رویداد مورد نظر وصل کنید. React تابع مدیریت رویداد را زمانی که کاربر روی دکمه کلیک میکند فراخوانی خواهد کرد.
بهروزرسانی صفحه
اغلب، شما میخواهید کامپوننت برخی اطلاعات را که نمایش می دهد "به خاطر بسپارد". به عنوان مثال، شاید بخواهید تعداد دفعاتی را که روی یک دکمه کلیک شده است، بشمارید. برای این کار، باید وضعیت را به کامپوننت خود اضافه کنید.
ابتدا، useState
را از React وارد کنید:
import { useState } from 'react';
حالا میتوانید یک متغیر وضعیت را درون کامپوننت خود تعریف کنید:
function MyButton() {
const [count, setCount] = useState(0);
// ...
شما از useState
دو چیز دریافت میکنید: وضعیت فعلی (count
) و تابعی که به شما اجازه میدهد آن را بهروزرسانی کنید (setCount
). میتوانید به آنها هر نامی بزنید، اما معمولاً کنوانسیون این است که بنویسیم [something, setSomething]
.
بار اول که دکمه نمایش داده میشود، count
برابر با 0
خواهد بود زیرا شما 0
را به useState()
پاس داده اید. زمانی که بخواهید وضعیت را تغییر دهید، setCount()
را فراخوانی کرده و مقدار جدید را به آن منتقل کنید. تا کلیک بر روی این دکمه شمارنده را افزایش دهد:
function MyButton() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
{count} بار کلیک شده
</button>
);
}
React دوباره تابع کامپوننت شما را فراخوانی خواهد کرد و این بار، count
برابر با مقدار 1
خواهد شد. با کلیک بعدی 2
خواهد بود و به همین ترتیب...
اگر همان کامپوننت را چندین بار رندر کنید، هر کدام از کامپوننت ها وضعیت مربوط به خود را خواهند داشت. مثلن در کد زیر اگر هر دکمه را جداگانه کلیک کنید، مقدار هر کدام جداگانه زیاد میشود:
مشاهده اجرای کد در CodeSandbox
import { useState } from 'react';
export default function MyApp() {
return (
<div>
<h1>شمارندههایی که به صورت جداگانه بهروزرسانی میشوند</h1>
<MyButton />
<MyButton />
</div>
);
}
function MyButton() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<button onClick={handleClick}>
{count} بار کلیک شده
</button>
);
}
توجه داشته باشید که هر دکمه چگونه وضعیت count
خود را "به خاطر می سپارد" و بر دیگر دکمهها تأثیر نمیگذارد.
استفاده از Hooks
توابعی که با use
شروع میشوند Hooks (هوک) نامیده میشوند. useState
یک هوک داخلی است که توسط React در اختیار شما قرار داده شده است. شما میتوانید دیگر هوک های داخلی را در مطلب مرجع API پیدا کنید. همچنین میتوانید با ترکیب هوک های موجود، هوک شخصی خود را بنویسید.
Hooks نسبت به دیگر توابع محدودتر هستند. شما تنها میتوانید Hooks را بالاترین سطح کامپوننت (یا هوک های دیگر) فراخوانی کنید. اگر میخواهید از useState
در یک شرط یا حلقه استفاده کنید، یک کامپوننت جدید درست کرده و آن را در آنجا قرار دهید.
به اشتراک گذاشتن دادهها بین کامپوننتها
در مثال قبلی، هر MyButton
وضعیت count
مستقل خود را داشت و وقتی هر دکمه کلیک شد، فقط count
دکمه کلیک شده تغییر کرد:

در ابتدا، وضعیت count
هر MyButton
0
است

اولین MyButton
وضعیت count
خود را به 1
بهروزرسانی میکند
اما گاهی نیاز دارید که کامپوننتها دادهها را به اشتراک بگذارند و با هم بهروزرسانی شوند.
برای اینکه هر دو کامپوننت MyButton
همان count
را نمایش دهند و با هم بهروزرسانی شوند، باید وضعیت را از دکمهها جدا و "به سمت بالا" به نزدیکترین کامپوننتی که شامل هر دوی آنها است، منتقل کنید.
در این مثال، آن کامپوننت MyApp
است:

در ابتدا، وضعیت count
MyApp
0
است و به هر دو فرزند منتقل میشود

با کلیک، MyApp
وضعیت count
خود را به 1
بهروزرسانی میکند و آن را به هر دو فرزند منتقل میکند
حالا وقتی که شما یکی از دکمهها را کلیک میکنید، count
در MyApp
تغییر خواهد کرد، که باعث تغییر هر دو count
در MyButton
میشود.
ابتدا، وضعیت را به سمت بالا حرکت دهید از MyButton
به MyApp
:
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>شمارندههایی که به صورت جداگانه بهروزرسانی میشوند</h1>
<MyButton />
<MyButton />
</div>
);
}
function MyButton() {
// ... ما در حال جابجایی کد از اینجا هستیم ...
}
سپس، مقدار وضعیت را به پایین منتقل کنید از MyApp
به هر MyButton
، همراه با تابع مدیریت کلیک مشترک. میتوانید اطلاعات را به MyButton
با استفاده از آکولاد و اتریبیوتهای JSX منتقل کنید، درست مانند کاری که قبلاً با تگهای داخلی مانند انجام دادهاید:
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>شمارندههایی که با هم بهروزرسانی میشوند</h1>
<MyButton count={count} onClick={handleClick} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}
اطلاعاتی که به این صورت منتقل میکنید props نامیده میشود. حالا کامپوننت MyApp
شامل وضعیت count
و رویداد handleClick
است و هر دو را به عنوان props به هر یک از دکمهها منتقل میکند.
در نهایت، MyButton
را تغییر دهید تا props را که از کامپوننت والد خود دریافت کرده است، در کد خود مورد استفاده قرار دهد:
function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
{count} بار کلیک شده
</button>
);
}
وقتی روی دکمه کلیک کردید، تابع هندلر onClick
اجرا میشود. هر دکمه هندلر onClick
را به تابع handleClick
داخل MyApp
وصل کرده است، بنابراین با کلیک روی دکمه کد داخل آن setCount(count + 1)
اجرا می شود و متغیر وضعیت count
را افزایش میدهد. سپس مقدار count
جدید به عنوان یک prop به هر دکمه منتقل میشود، بنابراین همه دکمه ها مقدار جدید را نشان میدهند. این را "بالا بردن وضعیت" مینامند. با حرکت دادن وضعیت به بالا، شما آن را بین کامپوننتها به اشتراک گذاشتهاید.
مشاهده کد و اجرای آن در CodeSandbox
import { useState } from 'react';
export default function MyApp() {
const [count, setCount] = useState(0);
function handleClick() {
setCount(count + 1);
}
return (
<div>
<h1>شمارندههایی که با هم بهروزرسانی میشوند</h1>
<MyButton count={count} onClick={handleClick} />
<MyButton count={count} onClick={handleClick} />
</div>
);
}
function MyButton({ count, onClick }) {
return (
<button onClick={onClick}>
{count} بار کلیک شده
</button>
);
}
مراحل بعدی
حالا شما با اصول اولیه نوشتن کدهای React آشنا شده اید!
آموزش ساخت بازی دوز را برای آشنایی بیشتر با مفاهیم این مطلب و استفاده عملی از آنها مطالعه کنید و اولین مینی اپ خود را با React بسازید.