ساخت صفحه انتخاب کاراکتر در React (بخش اول) – از صفر تا صد


React یک کتابخانه جاوا اسکریپت است که به طور عمده به جهت کمک به ساخت رابطهای کاربری عالی در عین حفظ سادگی مشهور شده است. وبسایتهای مشهور و بزرگی مانند فیسبوک، نتفلیکس و نیویورکتایمز وباپلیکیشنهای خود را با استفاده از React طراحی کرده و نگهداری میکنند. این کتابخانه به لطف مشارکت متن-باز زیادی که در آن وجود دارد، روز به روز بهبود زیادی پیدا میکند. در این مقاله مراحل ساخت یک صفحه انتخاب کاراکتر مقدماتی را با بهرهگیری از قابلیتهای React بررسی میکنیم. در این فرایند با روش حل برخی مسائل آشنا میشویم و امیدواریم این راهنما برای توسعهدهندگان تازهکار React مفید باشد. در نهایت صفحهای مانند زیر به دست خواهیم آورد:
با مراجعه به این ریپوی گیتهاب (+) میتوانید کد کامل بررسی شده در این راهنما را به همراه کاراکترهای بیشتر ملاحظه کنید.
ما برای ساخت جلوههای موجود در مثال این مقاله از هیچ کتابخانه UI استفاده نکردهایم و صرفاً یک اسپینر بارگذاری نصب کردهایم. دلیل این کار آن است که هر کس بتواند این راهنما را مطالعه کرده و نیازی به مطالعه API کتابخانهها برای درک مثالهای این راهنما نداشته باشد.
در این راهنما قصد داریم یک پروژه React را به سرعت با دستور create-react-app ایجاد کنیم. بنابراین در ادامه با دستور زیر یک پروژه میسازیم. ما پروژه خود را در این راهنما character-select نامیدهایم.
npx create-react-app character-select
در نهایت وارد دایرکتوری مربوطه میشویم:
cd character-select
درون مدخل اصلی src/index.js کمی تمیزکاری میکنیم:
استایلهای آغازین به صورت زیر هستند:
فایل src/styles.css
اکنون به فایل src/App.js میرویم و از عنصر root آغاز میکنیم، زیرا استایل ها را از قبل تعریف کردهایم:
پیش از آن که آغاز کنیم ابتدا گردش کار این صفحه انتخاب کاراکتر را توضیح میدهیم، بدین ترتیب مطمئن میشویم که همگی درک درستی از آن یافتهایم.
فرض کنید ما مشغول یک بازی MMORPG هستیم. همه بازیکنان با ایجاد یک کاراکتر آغاز میکنند. هر بازیکن به صورت پیشفرض با کلاس مبتدی (Novice) آغاز میکند. زمانی که به سطح 10 رسید، میتواند به کلاس دوم وارد شود. در این راهنما ما صرفاً کلاسهای Sorceress و Knight را داریم، اما در بازیهای MMORPG به طور معمول کلاسهای دیگری مانند Archer و Necromancer نیز وجود دارند.
زمانی که بازیکن به سطح 10 برسد و یک کلاس انتخاب کند، روی یک دکمه به نام Morph کلیک میکند و ظاهر کاراکتر وی بر همین اساس تغییر مییابد. این اقدامات به صورت خودکار موجب اسکرول به پایین صفحه میشود تا همه چیز تعاملی به نظر بیاید. در نهایت بازیکن به صفحه جدیدی هدایت میشود.
ابتدا کار خود را با ارائه صفحهای آغاز میکنیم که به بازیکنان خوشامدگویی میکند و سپس دو کلاس مختلف که میتوانید کاراکترشان را به آنها تبدیل کنند را نمایش میدهیم.
اگر بازیکن کلاس sorceress را انتخاب کند، میتواند به این نوع تبدیل شود و مسیر خود را برای تبدیل شدن به یک بازیکن بهتر در بازی ادامه دهد. همین مفهوم در مورد گزینه Knight نیز صدق میکند. اما یک گزینه مخفی نیز وجود دارد. اگر بازیکن به قدر کافی هوشمند و زیرک باشد، متوجه میشود که میتواند هر دو کلاس را انتخاب کند و به کاراکتری خارقالعاده تبدیل شود. زندگی پر از شگفتی است و بازی نیز باید بازتابی از زندگی باشد تا واقعگرایانه به نظر برسد.
ما برای عرضه صفحه قصد داریم بازیکنان را با یک هدر، یک تصویر از کلاس مبتدی (چون در ادامه هرگز آن را نخواهند دید) و یک پیام دلگرمکننده مواجه کنیم که جبرانی برای تلاش سختشان در بازی باشد.
فایل src/App.js
موارد زیر را نیز به فایل styles.css اضافه کنید:
اینک اگر به کامپوننت نگاه کنید، میبینید که عنصر root شامل یک هدر، یک کانتینر محتوا و یک هدر فرعی به عنوان فرزند بیواسطه است. اشاره کردیم که قصد داریم تصویری از یک مبتدی به کاربر نمایش دهیم. این همان کاری است که درون عنصر div با کلاسی به نام styles.content انجام میشود:
ما نماهای کلاس CSS را برای هدر و هدر فرعی تعریف کردهایم زیرا حس کردیم که این موارد ممکن است در ادامه در اینترفیسهای دیگر مانند زمانی که بازیکن به یک بخش جدید هدایت میشود، مورد استفاده مجدد قرار گیرند. منظور ما از کلمه «بخش» چیزی است که شامل هدر و یک بدنه است و از این رو حرکت مجازی به شمار میرود. همچنین میتوانیم از «کادر کاراکتر» (character box) برای کاراکترهای دیگر مانند mages یا مواردی دیگر استفاده کنیم و از این رو نام کلاس characterBox. را نیز برای نگهداری موارد مرتبط در ادامه تعریف کردیم.
اکنون که سادهترین بخش راهنما را تنظیم کردیم، میتوانیم به بخشهای جذابتر برسیم.
کار بعدی که باید انجام دهیم این است که صفحههای options یا selection را بسازیم. این صفحه مسئول نمایش دادن بخش انتخاب کلاس کاراکتر به بازیکن است. این کاراکترها به نام Sorceress و Knight نامیده میشوند. این همان صفحهای است که بازیکنان به محض رسیدن به سطح 10 مشاهده میکنند.
برای اجرای مؤثر این کار باید در مورد هدف گام بعدی برای بازیکن فکر کنیم. هدف این صفحه برای بازیکنها آن است که ین یک کاراکتر Sorceress و Knight انتخاب کنند، از این رو داشتن یک کادر انتخاب کاراکتر و عرضه آن به بازیکن مناسب خواهد بود.
اکنون باید از ایجاد کامپوننتهای چندگانه که اساساً کار یکسانی را انجام میدهند تا حد امکان احتراز کنیم. انجام این کار رویه مناسبی محسوب نمیشود چون در آینده برای بازگشت به کد و تغییر دادن آن به هر دلیل احتمالی دچار مشکل خواهید شد. همچنین در زمان دیباگ کردن اشکالهای کوچک با مشکل مواجه میشوید.
با در نظر گرفتن موارد فوق، در section بعدی که به گزینههای انتخاب کاربر مربوط است، میتوانید آن را مانند بخش قبلی سازماندهی کنید، یعنی دارای هدر، محتوا/بدنه و هدر فرعی باشد.
ما از این مفهوم دوباره استفاده میکنیم تا صفحه انتخاب کاراکتر را با تجرید هدر، هدر فرعی و کانتینر (یا محتوا) ایجاد کنیم.
به طور معمول این کامپوننتهای با قابلیت استفاده مجدد را در فایلهای مجزایی قرار میدهیم و بدین ترتیب میتوانیم مستقیماً آنها را به صورت ماژولهای منفردی import کنیم. از طرف دیگر برای صرفهجویی در زمان و فضا آنها را در مسیر src/components.js قرار میدهیم.
در این بخش یک فایل به نام components.js در همان دایرکتوری ایجاد میکنیم و موارد با استفاده مجدد را به نام exports در آن تعریف میکنیم:
فایل src/components.js
اکنون کامپوننت App را با این کامپوننت جدید که قابلیت استفاده مجدد دارد تعویض میکنیم:
فایل src/App.js
چنان که میبینید کد اینک زیباتر شده است. بنابراین در ادامه کاری میکنیم که صفحه کلاسهای کاراکتر را نشان دهد:
فایل src/App.js
در کد فوق یک مورد جدید به styles.module.css اضافه میکنیم:
با این تغییر، اینترفیس ما اینک به صورت زیر در میآید:
در کد میبینید که میتوانیم از Header ،Subheader و Content برای بخش بعدی نیز استفاده کنیم. اینک اینترفیس یکنواخت به نظر میرسد و مزیت عمدهای به دست آوردهایم: ما اکنون تنها کافی است کامپوننتهای هدر/هدر فرعی/ محتوا را به جای چند جای مختلف، صرفاً در یک جای منفرد تغییر دهیم.
برخی مزیتهای قابل توجه دیگر که از این رویکرد به دست میآید، «مستندسازی ضمنی» (implicit documentation) است. بدین ترتیب مطمئن میشویم که این کامپوننتهای هدر و هدر فرعی در مراجعات بعدی به راحتی قابل درک خواهند بود.
بخش بعدی که میخواهیم بسازیم این است که کادرهای Sorceress و Knight به محض کلیک شدن باید نوعی عمل اجرا کنند.
تا این جا صرفاً یک دستگیره onSelect بیاستفاده تعریف کردهایم، بنابراین نوعی structure تعریف میکنیم تا بتوانیم به طور ثابت یادآوری کنیم که برای استفادههای بعدی به نوعی اکشن کلیک نیاز داریم:
اینک همه چیز عالی به نظر میرسد، اما بدون وجود یک نوع تغییر بصری، بازیکن هیچ راهی برای دانستن این که کدام کاراکتر انتخاب شده است، نخواهد داشت:
ابتدا با ایجاد یک جلوه hover آن را کمی تعاملیتر میسازیم که یک گام کوچک رو به جلو محسوب میشود، زیرا بسیار بهتر از تصویر ثابت است.
اکنون از آنجا که میخواهیم نامهای کلاسها را در هم ادغام کنیم تا چند جلوه به صورت موازی برای عناصر منفرد رخ بدهند، باید کتابخانه کارآمد classnames (+) را برای اجرای ادغام نصب کنیم:
npm install --save classnames
قدرت کتابخانه classnames زمانی رخ مینماید که بخواهید نامهای کلاس را بر مبنای شرایط خاصی اعمال کنید. ما به این امکان نیاز خواهیم داشت، زیرا عناصر خاصی باید در مواقع خاصی پنهان یا نمایان شوند.
اینک برخی استایلها را به عناصر کادر کاراکتر اضافه میکنیم:
زمانی که بازیکن روی این کادرها میرود، برای برجستهتر کردن آن، یک فیلتر hue-rotate که مداوماً تغییر مییابد اعمال میکنیم. بدین ترتیب بازیکن برای تبدیل شدن به کلاس دوم هیجان خواهد داشت.
در حال حاضر این جلوه hover هیچ کاری انجام نمیدهد، زیرا باید نامهای کلاس جدید را چنان که نمایش یافته در CSS اعمال کنیم. تنها کاری که باید انجام دهیم، اعمال خصوصیت className روی عناصر تصویر tier2 است.
فایل src/App.js
اینک یک جلوه hover تغییر رنگ داریم:
اکنون که جلوه hover را داریم باید یک استایل برای مواردی که یکی از آنها انتخاب میشوند نیز داشته باشیم. این بدان معنی است که باید برخی استایلها زمانی که کاربر کاراکتری را انتخاب میکند حفظ شوند.
بدین ترتیب باید از قلابهای react استفاده کنیم. یک قلاب سفارشی به نام useLevelUpScreen درست بالای کامپوننت App میسازیم و حالت select را همراه با دستگیره onSelect برای بهروزرسانی آن تعریف میکنیم:
فایل src/App.js
درون useLevelUpScreen حالت selected را تعریف کردهایم که به ما کمک میکند تعیین کنیم بازیکن کدام کلاس tier2 را انتخاب کرده است. دستگیره onSelect همان API برای بهروزرسانی حالت محسوب میشود. این API از نسخه callback مربوط به useState جهت تضمین این که آخرین بهروزرسانی را در حالت selected دریافت کرده است بهره میجوید. درون callback بررسی میکند که آیا type (که در این مثال Knight یا Sorceress است) قبلاً انتخاب شده است یا نه. اگر چنین باشد فرض میکنیم که بازیکن تصمیم گرفته است، انتخاب خود را لغو کند و از این رو آن را برای بهروزرسانی بعدی حالت فیلتر میکنیم و یا برعکس.
سپس دستگیره onSelect را روی عناصری که در کامپوننت App به آن نیاز دارند اعمال میکنیم:
فایل src/App.js
اینک باید بهروزرسانیها را روی کاراکترهایی که انتخاب میشوند و یا نمیشوند دریافت کنیم. البته این حالت هنوز در رابط کاربری برای بازیکن بازتاب نمییابد، زیرا آن را هنوز روی کامپوننت اعمال نکردهایم، این کار را در بخش بعدی انجام میدهیم. در نخستین گام قصد داریم از پکیج classnames برای اعمال مشروط نام کلاس روی عناصر به صورت زیر استفاده کنیم.
فایل src/App.js
با افزودن این استایلهای جدید، باید استایلها را بهروزرسانی کنیم تا از آنها استفاده کنند.
فایل src/styles.css
توجه کنید که .characterBox img.selected پس از خط hover و به عنوان همنیا الحاق یافته است.
با این تغییر اینک دو کادر انتخاب کاراکتر واکنشپذیر زیبا داریم:
در اوایل این راهنما اشاره کردیم که اگر بازیکن به قدر کافی زیرک و هوشیار باشد میتواند درک کند که امکان انتخاب همزمان هر دو تبدیل Sorceress و Knight وجود دارد تا با چیز غیرمنتظرهای مواجه شود که یک کاراکتر پنهان است. بدیهی است که میخواهیم نوعی عناصر UI در ا اختیار بازیکن قرار دهیم تا بتوانند کلاس مبتدی خود را به نیابت از آن تغییر دهند و به این منظور به یک button نیاز داریم.
به این ترتیب یک button ساده مینویسیم. یک دستگیره onMorph به آن الحاق میکنیم که قصد داریم به همراه اعمال styles.morph روی className دکمه ایجاد کنیم:
فایل src/App.js
اگر به آنچه از قلاب useLevelUpScreen بازمیگردد نگاه کنید، میبینید که دو مورد morphed و onMorph اضافه شدهاند. این موارد قرار است درون یک قلاب سفارشی تعریف شوند.
فایل src/useLevelUpScreen.js
در این بخش استایل نام کلاس styles.morph به صورت زیر است.
فایل src/styles.module.css
نتیجه کار نیز تا به این جا چنین بوده است:
بهتر است دکمه morph را تا زمانی که بازیکن کاراکتری را انتخاب نکرده است پنهان کنیم تا تمرکز بازیکن روی انتخاب یک کلاس کاراکتر باشد. بنابراین یک جلوه پنهان روی آن اعمال میکنیم تا زمانی که selected به صورت زیر برقرار شود:
نکته: ما دکمه را درون یک عنصر div قرار دادهایم تا بتوانیم یک کنترل دقیقتر روی موقعیت و فاصلهبندی دکمه داشته باشیم.
اینک بازیکن به خوبی میداند که وی باید چیزی را انتخاب کند چون این تنها گزینهای است که پیش روی او قرار گرفته است:
این دکمه کمی ساده به نظر میرسد. ما میخواهیم بازیکن با انگیزه بماند و از این که تا این سطح 10 آمده است خوشحال باشد. بنابراین در گام بعدی آیکونهایی در سمت چپ و راست دکمه morph قرار میدهیم که میتوان با نصب react-icons آنها را تعریف کرد:
npm install --save react-icons
نکته: اگر در زمان نصب پکیج با استفاده از NPM با خطایی مواجه شدید، تلاش کنید آن را با دستور yarn نصب کنید و پکیج را با دستور زیر مجدداً اضافه کنید:
yarn add react-icons
پس از آن میتوانید دوباره به NPM بازگشته و سرور را آغاز کنید. سپس این کامپوننت آیکون را ایمپورت میکنیم:
import { MdKeyboardTab } from 'react-icons/md'
ما یک آیکون فلش راست قبل و یک آیکون هم پس از آن قرار دادیم. اینک آیکونهای فلش ثابت هستند و به سمت دکمه اشاره میکنند. باید با استایلبندی به آنها جان ببخشیم و از این رو جلوه تغییر رنگ با تغییر مداوم به آنها میدهیم. علاوه بر این آیکون فلش سمت راست را نیز طوری اصلاح میکنیم که به سمت داخل اشاره کند:
استایلهایی که استفاده شده است به صورت زیر بودهاند.
فایل src.styles.module.css
اینک وقتی این صفحه را با نسخههای قبلی مقایسه میکنیم میبینیم که بازیکنها انگیزه بسیار بیشتری برای آغاز فصل بعدی پیدا میکنند.
بدین ترتیب به پایان بخش اول این آموزش می رسیم، برای دیدن بخش دوم روی لینک زیر کلیک کنید:
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای برنامهنویسی
- مجموعه آموزشهای JavaScript (جاوا اسکریپت)
- واکشی (Fetch) کردن داده ها در اپلیکیشن های React — به زبان ساده
- ۲۲ ابزار مهم برای توسعه دهندگان React — فهرست کاربردی
- آموزش ری اکت (React) — مجموعه مقالات مجله فرادرس
==