۶ روش برای بهبود کدهای ری اکت | راهنمای کاربردی

هر توسعهدهندهای که به تازگی با یک زبان برنامهنویسی و یا فریمورک آشنا میشود، دوست دارد که هر چه سریعتر مهارت خود را ارتقا داده در آن زمینه به یک فرد خبره تبدیل شود. بهترین روش برای نیل به این مقصود، بهرهگیری از توصیههای برنامهنویسان باتجربهتر است. تا انتهای این مقاله با ما همراه باشید تا با ۶ روش برای بهبود کدهای ری اکت (React) آشنا شوید.
ESLint + TypeScript
جاوا اسکریپت یک زبان با «نوعبندی سست» (loosely typed) است. در زمان استفاده از جاوا اسکریپت میتوانیم هر مسئله را به هزاران روش مختلف حل کنیم. جاوا اسکریپت خودش به تنهایی نمیتواند مانع ما شود که کدهای دارای باگ و یا کدی با عملکرد پایین ننویسیم. اما خوشبختانه میتوانیم از دو ابزار مختلف برای تحلیل استاتیک کد خود بهره بگیریم که شامل Typescript و ESLint هستند.
ما با بهرهگیری از ESLint میتوانیم کد خود را به صورت استاتیک تحلیل کنیم و مشکلات مختلف آن را پیش از اجرا دریابیم. همچنین میتوانیم استانداردهای مختلف را الزام کرده و قابلیت نگهداری کدبیس خود را افزایش دهیم.
برای نمونه میتوانیم پلاگین eslint-plugin-react-hooks را نصب کنیم. این پلاگین کد جاوا اسکریپت به ظاهر خوب زیر را میگیرد و به ما اعلام میکند که این کد «قاعده قلابها» (rule of hooks) را نقض کرده است:
// ? We're breaking the first rule by using a Hook in a condition if (userName !== '') { useEffect(function persistForm() { localStorage.setItem('formData', userName); }); }
همچنین میتوانیم از سیستم نوعبندی استاتیک در تایپ اسکریپت بهره بگیریم تا باگها را پیش از وارد شدن به کدبیس شناسایی کنیم. تایپ اسکریپت Intellisense قدرتمند و مفیدی ارائه میکند که موجب میشود کار با کامپوننتها و کتابخانهها سرعت بسیار بیشتری پیدا کند. تایپ اسکریپت سرعت بازسازی کد را بالا میبرد و برخی رویههای مناسب مانند استفاده از ژنریک را الزام میکند.
با تبدیل شدن به یک برنامهنویس خوب در تایپ اسکریپت، نه تنها مهارت جاوا اسکریپت شما افزایش مییابد، بلکه میتوانید کد بهتری نیز برای React بنویسید.
از قلابها بهره بگیرید
از زمانی که قلابهای ریاکت در فوریه 2019 معرفی شدهاند، با سرعتی طوفانی دنیای ریاکت را تسخیر کردند. با این که تیم ریاکت توصیه نمیکند که کدهای قدیمی را برای بهرهگیری از قلابها بازنویسی کنیم، اما امروزه قلابها در همه جا حضور دارند اگر میخواهید در زمینه برنامهنویسی ریاکت پیشرفت کنید، بهترین چیز این است که زمان خود را صرف درک بهتر قلابهای ریاکت بکنید.
اگر نیاز به اجرای برخی کارهای جنبی دارید، از useEffect بهره بگیرید. اگر میخواهید حالت را بین رندرهای مختلف ردگیری کنید، از قلاب useState استفاده کنید. اگر میخواهید یک مقدار را بین رندرها ذخیره کرده و بهروزرسانی نمایید، یا لازم است که ارتفاع یا عرض یک عنصر DOM را بررسی کنید، از قلاب useRef استفاده کنید.
برای نمونه در ادامه یک مثال از کاربرد useEffect را مشاهده میکنید. فرض کنید میخواهیم عنوان صفحه را هر زمان که دکمهای کلیک میشود (به صورت یک عارضه جانبی) بهروزرسانی کنیم.
useEffect(() => { document.title = `You clicked ${count} times`; }); // runs on every render
ما میتوانیم قلاب خود را به آسانی طوری بهینهسازی کنیم که به جای اجرا شدن در هر بار رندر، تنها زمانی اجرا شود که متغیر count تغییر مییابد. این کار با افزودن count به آرایه وابستگی میسر است.
useEffect(() => { document.title = `You clicked ${count} times`; }, [count]); // Only re-run the effect if count changes
استفاده از قلابهای رایج ریاکت و یا ایجاد قلابهای سفارشی، دشواری خاصی ندارد. همچنین باید درک خوبی از این موضوع داشته باشید که چه زمانی باید از یک قلاب مانند useEffect که منجر به رندر مجدد میشود استفاده کنید و چه زمانی نباید این کار را انجام دهید.
اجتناب از بهینهسازی زودهنگام
در موارد متعددی دیده میشود که توسعهدهندگان تازهکار React تلاش میکنند تا کد خود را طوری بنویسند که تا بیشترین حد ممکن بهینه باشد. useMemo و useCallback دو قلاب رایج هستند که برای بهینهسازی کد ریاکت مورد استفاده قرار میگیرند. اما چه زمانی باید از آنها استفاده کرد و چه زمانی نباید از آنها بهره گرفت؟
در ادامه به بررسی یک کامپوننت ساده میپردازیم که یک آرایه از آبنباتها را به عنوان prop میگیرد. این کامپوننت به فیلتر کردن آرایه پرداخته و نام هر آبنبات را با نوع شکلات نمایش میدهد.
برخی توسعهدهندگان ممکن است فکر کنند که نوشتن چنین کدی زشت است. ممکن است با خود بیندیشند که باید فهرست شکلاتها را در زمان تغییر یافتن آبنباتها تغییر دهند. اما نتیجه کار ایجاد کدی است که خواندن آن دشوار است و سربار زیادی دارد.
const Chocolate = (props) => { const chocolates = useMemo( () => props.candies.filter((candy) => candy.type === "chocolate"), [props.candies] ); return ( <> {chocolates.map((item) => ( <p>{item.name}</p> ))} </> ); };
به جای آن بهتر است کد ساده و تمیز بنویسیم. دلیلی برای استفاده از useMemo در مواردی این چنین وجود ندارد. ما باید از useMemo یا useCallback صرفاً برای به خاطر سپردن نتیجه عملیات سنگین از نظر محاسباتی استفاده کنیم. توصیه کلی این است که تا وقتی با مشکل عملکردی جدی مواجه نشدهاید، اقدام به بهینهسازی کد اپلیکیشن خود نکنید.
لزومی ندارد که در همه جای اپلیکیشن از useCallback و useMemo بهره بگیرید. لزومی ندارد که همه چیز را بهینهسازی کنید. صبر کنید تا مشکلی پیدا شود و آنگاه آن را حل کنید. سری که درد نمیکند را دستمال نمیبندند.
چه زمانی به کامپوننت جدید نیاز داریم؟
بسیاری از توسعهدهندگان تازهکار ریاکت منطق تجاری را با آن چه که باید محاسبات ارائهای محض باشد، در هم میآمیزند. برای این که کد شما تا حد امکان، خوانایی زیادی داشته باشد، بهتر است تا بیشترین حد ممکن خوانا بنویسید.
برای نیل به این مقصود باید بین کامپوننتهای ارائهای و کامپوننتهایی که شامل منطق هستند، تمایز قائل شوید. در گذشته رایج بود که کامپوننتها به دو دسته کانتینر و کامپوننت تقسیم میشدند. امروزه از این روش استفاده نمیشود.
به کامپوننت زیر نگاه کنید که در یک کامپوننت واحد، یک لیست از آیتمها را واکشی میکند و اطلاعات آنها را نمایش میدهد.
const ListItems = () => { const items = React.useState([]); React.useEffect(() => { async function fetchItems() { await fetched = fetchItems(); setItems(fetched); } }); return ( <> {items.map((item) => ( <div className="item-container"> <img src={item.img} /> <div className="name">{item.name}</div> <div className="author">{item.author}</div> </div> ))} </> ); };
ممکن است وسوسه شویم که از رویکرد فوقالذکر کانتینر استفاده کنیم. در این رویکرد باید در نهایت دو کامپوننت مانند زیر داشته باشیم:
const ListContainer = () => { const items = React.useState([]); React.useEffect(() => { async function fetchItems() { await fetched = fetchItems(); setItems(fetched); } }); return <List items={items} />; }; const List = (props) => { return ( <> {props.items.map((item) => ( <div className="item-container"> <img src={item.img} /> <div className="name">{item.name}</div> <div className="author">{item.author}</div> </div> ))} </> ); };
اما به جای این رویکرد میتوانیم بخشهای ارائهای محض را تجرید کنیم تا در نهایت دو کامپوننت به نامهای List و Item داشته باشیم:
const List = () => { const items = React.useState([]); React.useEffect(() => { async function fetchItems() { await fetched = fetchItems(); setItems(fetched); } }); return ( <> {items.map((item) => ( <Item item={item} /> ))} </> ); }; const Item = ({ item }) => { return ( <div className="item-container"> <img src={item.img} /> <div className="name">{item.name}</div> <div className="author">{item.author}</div> </div> ); };
جدیت در تست کردن
تست کردن به تنهایی بزرگترین عاملی است که یک توسعهدهنده تازهکار را از یک توسعهدهنده باتجربه متمایز میسازد. اگر با روش تست کردن اپلیکیشنهای ریاکت آشنا باشید، روشهای زیادی برای افزایش سرعت کار خود خواهید یافت.
ممکن است شما در گذشته چند تست Unit اجرا کرده باشید، اما آیا در زمینه نوشتن تستهای integration برای کل اپلیکیشن نیز مهارت دارید؟ تلاش کنید از روشهای گوناگون برای ارتقای این مهارت خود بهره بگیرید، چون حائز اهمیت بسیار بالایی است.
درک تفاوت حالت سراسری و محلی
راهکارهای مختلف زیادی از قبیل Redux ،mobx ،recoil ،context API و غیره برای مدیریت حالت در ریاکت عرضه شدهاند و گزینههای زیادی به این منظور وجود دارند. صرفنظر از روشی که برای مدیریت حالت انتخاب میکنید، باید توجه داشته باشید که هرگز نباید کاربرد حالت سراسری را با کاربردهای محلی در هم بیامیزید. متأسفانه هیچ قاعده سریع و آسانی برای درک کاربردهای هر یک از این دو وجود ندارد. اما در ادامه برخی سرنخهای مهم را مطرح میکنیم.
برخی قواعد برای استفاده از حالتهای سراسری:
- در مواردی که کامپوننتهای دیگر اپلیکیشن نیاز به دسترسی به دادههای این کامپوننت (از قبیل نام کاربری که در navbar و یا صفحه خوشامدگویی نمایش مییابد) را داشته باشد.
- حفظ دادهها در زمان حرکت بین صفحههای مختلف.
- استفاده از دادههای یکسان در کامپوننتهای مختلف.
در موارد فوق باید از حالت سراسری (Global) استفاده شود، اما توجه کنید که نباید حالت open منو را حالت سراسری قرار دهید. همواره باید در مورد دلایل نیاز به اشتراک یک چیز در همه اپلیکیشن و یا قرارگیری آن در یک کامپوننت محلی تأمل کنید.
سخن پایانی درباره بهبود کدهای ری اکت
به این ترتیب به پایان این مقاله با موضوع معرفی 6 روش برای بهبود کدهای ری اکت میرسیم. زمانی که تجربه کمی در زمینه کدنویسی دارید، رعایت رویههای مناسب کدنویسی کار دشواری به نظر میرسد، اما به مرور که تجربه بیشتری کسب میکنید، این موارد را به صورت ناخودآگاه رعایت میکنید. توجه داشته باشید که فقط برنامهنویسان مبتدی هستند که کدهای پیچیده مینویسند. هر چه تجربه کدنویسی بالاتر برود، برنامهنویس کدهای سادهتری خواهد نوشت.