Anophel-آنوفل چگونه کد ReactJS خود را بهبود دهید|نکاتی برای خوانایی کد و بهره‌وری

چگونه کد ReactJS خود را بهبود دهید|نکاتی برای خوانایی کد و بهره‌وری

تاریخ انتشار:
React
زمان مطالعه: 16 دقیقه
<p>ReactJS یکی از محبوب‌ترین کتابخانه‌های جاوااسکریپت برای ساخت برنامه‌های قابل مقیاس و با عملکرد بالا است.</p><p>وقتی که بر روی پروژه‌های ReactJS کار می‌کنید، بگیرد که آنها بزرگ یا کوچک باشند، باید بر روی کیفیت کد، خوانایی، قابل نگهداری و قابل مقیاس بودن تمرکز کنید.</p><p>نوشتن کد خوب همچنین به شما کمک می‌کند تا توضیحاتی که هم‌تیمی‌هایتان می‌دهند (و صادقانه باشیم - کی دوست ندارد توضیحاتی مثل "با تشکر، تایید شده" را بخواند :) ) را کاهش دهید.</p><p>در این آموزش، شما یاد خواهید گرفت که چگونه کد React خود را بهبود دهید. من نکات مورد علاقه خود را به همراه نمونه‌های کد به اشتراک خواهم گذاشت تا به شما نشان دهم که چگونه همه چیز کار می‌کند. این نکات به شما کمک می‌کنند تا کد قابل نگهداری، قابل مقیاس و قابل خواندنی بنویسید.</p><p>برای بهره‌گیری حداکثری از این راهنما، باید با React آشنایی اولیه داشته باشید.</p><p>&nbsp;</p><h2><span style="font-size:35px;"><strong>1- </strong><span style="-webkit-text-stroke-width:0px;display:inline !important;float:none;font-style:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-weight:400;letter-spacing:normal;orphans:2;text-align:start;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:pre-wrap;widows:2;word-spacing:0px;"><strong>استفاده از ثابت‌ها</strong></span></span></h2><p>&nbsp;</p><p>در جاوااسکریپت، ما می‌توانیم با استفاده از کلمه کلیدی `const` ثوابت را اعلام کنیم. این به ما کمک می‌کند تا از دوباره اعلام کردن یک مقدار جلوگیری کنیم. بنابراین، ثوابت گزینه‌ی عالی‌ای برای ذخیره کلیدهای API و مقادیر مشابه می‌باشند.</p><p>ثوابت به بهره‌وری، خوانایی، و بین‌المللی‌سازی هر کد React کمک می‌کنند.</p><p>در هر پروژه‌ی ReactJS، باید از هارد‌کد کردن رشته‌ها (محتوا) در کامپوننت‌های خود پرهیز کنید.</p><p>این کار باعث می‌شود پروژه‌ی شما قابل نگهداری‌تر، قابل مقیاس‌تر، و قابل خواندن‌تر شود، زیرا لایه‌های رابط کاربری (UI)، داده، و محتوا را از یکدیگر جدا می‌کند.</p><p>ثوابت شامل موارد زیر می‌شوند:</p><p>&nbsp;</p><ul><li style="margin-right:40px;">API keys<br>&nbsp;</li><li style="margin-right:40px;">URLs<br>&nbsp;</li><li style="margin-right:40px;">Content</li></ul><p>&nbsp;</p><p>بسیاری از وب‌سایت‌ها از چندین زبان مانند انگلیسی، فرانسوی، اسپانیایی و غیره پشتیبانی می‌کنند. این به عنوان بین‌المللی‌سازی (یا i18n به اختصار) شناخته می‌شود.</p><p>اگر شما ویژگی‌های بین‌المللی‌سازی را در وب‌سایت خود فعال می‌کنید، باید فایل‌های ثابت جداگانه برای محتوای خود ایجاد کنید - به عنوان مثال en.js و fr.js. حتی اگر پشتیبانی از چندین زبان ندارید یا بدون بین‌المللی‌سازی، همچنان بهتر است محتوای خود را خارج از کد در یک فایل ثابت نگه دارید.</p><p>شما می‌توانید فایل ثابت خود را به دو صورت نامگذاری کنید: [زبان_مخفف].js یا <code>constants.js</code>. این نام‌های فایل‌ها رایج‌ترین نام‌هایی هستند که توسعه‌دهندگان برای این منظور استفاده می‌کنند.</p><p>&nbsp;</p><h3><span style="font-size:22px;"><strong>چگونه فایل ثابت خود را ایجاد کنید:</strong></span></h3><p>ثوابت به سادگی شیء‌های جاوااسکریپت با کلید/مقدار‌ها هستند. ابتدا یک شیء را با یک نام که محتوایی که نگه می‌دارد را بازتاب می‌دهد، اعلام کنید. چون این مقادیر رشته‌ها هستند، برای آن‌ها از نقل قول استفاده می‌کنیم. قبل از صادر کردن (export) پیام‌ها، از ()Object.freeze استفاده کنید - این باعث می‌شود هیچ تغییری از خارج به اتفاقی در مقدار هیچ کلیدی انجام نشود.</p><p>برای استفاده از ثوابت، باید فایل ثابت را در فایل کامپوننت خود وارد کنید (import) و پس از وارد کردن آن، می‌توانید با استفاده از عملگر نقطه (dot operator) به کلیدها دسترسی پیدا کنید:</p><p>&nbsp;</p><pre><code class="language-javascript">// constants.js or en.js const MESSAGES = { 'HEADING': 'welcome to the website", 'ENTER_YOUR_NAME': 'Enter user name', 'HOME': [{ 'HEADING': 'welcome to the home' }] }

Object.freeze(MESSAGES);

export default MESSAGES;</code></pre><p> </p><pre><code class="language-javascript">// Using constants.js in component import MESSAGES from '../constants/constants const Home = () => { return( <p>{MESSAGES.HEADING}</h1> ) } export default Home; </code></pre><p> </p><p> </p><h2><span style="font-size:35px;"><strong>2- </strong><span style="-webkit-text-stroke-width:0px;display:inline !important;float:none;font-style:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-weight:400;letter-spacing:normal;orphans:2;text-align:start;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:pre-wrap;widows:2;word-spacing:0px;"><strong>استفاده از Helpers / Utils:</strong></span></span></h2><p> </p><p>در حین کار بر روی یک کد ReactJS، شناسایی قسمت‌هایی در کد که می‌توانند به عنوان کمک‌ها یا ابزارهای کمکی مستقل از کامپوننت‌ها عمل کنند، بسیار مهم است.</p><p>کمک‌ها یا ابزارهای کمکی مسئول انجام وظیفه‌هایی هستند که ممکن است در چندین نقطه مختلف و توسط چندین توسعه‌دهنده مورد استفاده قرار گیرند. به عنوان مثال، تغییر فرمت تاریخ، تشکیل رشته، کد فراخوانی API، و مدیریت DOM از جمله مواردی هستند که می‌توانند در این دسته قرار گیرند.</p><p> </p><h3><span style="font-size:22px;"><strong>چرا از کمک‌ها یا ابزارهای کمکی استفاده کنیم؟</strong></span></h3><p><br>هر کامپوننت باید فقط مسئول یک وظیفه باشد که به عنوان "اصل مسئولیت تکی" شناخته می‌شود.</p><p>ما باید توابع قابل استفاده مجدد را شناسایی کنیم و آنها را به کمک‌ها (Utils) منتقل کنیم به دلایل زیر:</p><p> </p><p><span style="font-size:18px;">1. منجر به کامپوننت‌های تمیزتر و کد تمیزتر می‌شود.</span><br><span style="font-size:18px;">2. انسجام تنگاتنگی (Tight coupling) وابستگی به حداقل می‌آید.</span><br><span style="font-size:18px;">3. امکان‌پذیری توسعه به راحتی افزایش می‌یابد.</span><br><span style="font-size:18px;">4. نگهداری و اشکال‌زدایی ساده‌تر می‌شود.</span><br><span style="font-size:18px;">5. افزایش قابلیت استفاده مجدد.</span></p><p><span style="font-size:18px;">کامپوننت‌ها حالا تنها مسئول رابط کاربری (UI) هستند.</span></p><p> </p><pre><code class="language-javascript">``` // dateUtils.js : Moved the formatDate to a seprate util file to have reusability export function formatDate(date) { const options = { year: 'numeric', month: 'long', day: 'numeric' }; return new Date(date).toLocaleDateString(undefined, options); }</code></pre><p> </p><pre><code class="language-javascript">// Updated Blog.jsx component after util import React, { Component } from 'react'; import { formatDate } from './dateUtils'; const Blog = ({title, content, date}) => {    return ( <div> <h2>{title}</h2> <p>{content}</p> <p>Published on: {formatDate(date)}</p> </div> ); } }</code></pre><p> </p><p> </p><p>مثالی که در کد بالا دیده می‌شود، ما یک تابع به نام <code>formatDate</code> داخل کامپوننت <code>Blog </code>داریم. در اینجا می‌توانیم <code>formatDate</code> را به کمک‌ها (Utils) منتقل کنیم. چرا؟</p><p> </p><p>1. <code>formatDate</code> مسئول فرمت‌بندی تاریخ است و نه مسئول نمایش تاریخ.<br>2. <code>formatDate</code> ممکن است توسط کامپوننت دیگری استفاده شود.<br>3. <code>formatDate</code> ممکن است بر اساس نیازهای کسب‌وکار فرمت‌های مختلفی داشته باشد. به عنوان مثال، در حال حاضر ما یک پارامتر دوم بر اساس نیازهای این کامپوننت ارسال می‌کنیم. اگر نیازهای جدیدی پیش بیاید، توسعه‌دهنده باید کامپوننت را دوباره بنویسد.</p><p>با انتقال formatDate به کمک‌ها، این تابع تبدیل به یک ابزار کمکی (Utility) می‌شود که می‌تواند توسط هر کامپوننتی استفاده شود و تغییرات در فرمت‌بندی تاریخ را باعث تغییر در یک مکان مرکزی می‌کند، بدون نیاز به تغییر در همه کامپوننت‌ها که از آن استفاده می‌کنند. این به عنوان یک مثال از مدیریت مناسب کد و جلوگیری از تکرار کد و اشکال‌زدایی آسان در آینده خدمت می‌کند.</p><p> </p><h2><span style="font-size:35px;"><strong>3- </strong><span style="-webkit-text-stroke-width:0px;display:inline !important;float:none;font-style:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-weight:400;letter-spacing:normal;orphans:2;text-align:start;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:pre-wrap;widows:2;word-spacing:0px;"><strong>یادگیری چگونگی استفاده از Props</strong></span></span></h2><p> </p><p>برای ارتباط بین کامپوننت‌ها در ReactJS، از <code>Props </code>استفاده می‌کنیم. اما راه‌های مختلفی برای انجام این کار وجود دارد.</p><p>مهم است که فقط یک سبک برای مصرف Props در کامپوننت‌های کد شما انتخاب کنید. این باعث می‌شود که کد یکپارچه باشد. بیش از یک روش برای از بین بردن Props وجود دارد، به همین دلیل برای یکپارچگی و خواناتری کد خود فقط یک روش را انتخاب کنید.</p><p>بیایید در مورد راه‌هایی که می‌توانید با Props در React کار کنید، صحبت کنیم.</p><p> </p><h3><span style="font-size:22px;"><strong>چگونگی استفاده از </strong><code><strong>Props</strong></code></span></h3><p> </p><p>در این رویکرد، ما باید هر بار که می‌خواهیم از <code>props</code> استفاده کنیم، <code>props </code>را تکرار کنیم.</p><p>این رویکرد یک روش عالی برای مصرف <code>props </code>نیست چرا که ما هر زمان که می‌خواهیم از آنها استفاده کنیم، از آنها تکرار می‌کنیم. علاوه بر تکرار بودن، زمانی که به ایجاد <code>props </code>تو در تو می‌آید، نیاز به تایپ زیادی دارد.</p><p>زمان شما به عنوان یک توسعه‌دهنده مهم است، و ما می‌خواهیم کد را هر جا که ممکن است بهینه‌سازی کنیم و چیزها را تکرار نکنیم مگر اینکه کاملاً ضرور باشد.</p><p>در مثال کد زیر، می‌توانید ببینید که چرا این رویکرد بهترین گزینه نیست. ما کامپوننت <code>Input </code>را داریم که دارای <code>props </code>مانند <code>type</code>، <code>placeholder</code>، <code>name </code>و <code>changeHandler </code>است. در بخش بازگشت، ما با هر ویژگی مانند <code>props.type</code>، <code>props.placeholder</code>، و غیره، <code>props </code>را تکرار می‌کنیم.</p><p> </p><pre><code class="language-javascript">const Input = (props) => { return <input type={props.type} placeholder={props.placeholder} name={props.name} className="block p-2 my-2 text-black" onChange={props.changeHandler}/> } export default Input;</code></pre><p> </p><p> </p><h3><span style="font-size:22px;"><strong>چگونگی از بین بردن (Destructuring) Props</strong></span></h3><p> </p><p>در رویکرد دوم برای کار با <code>props</code>، از متغیردهی تخریبی (destructuring) جاوااسکریپت استفاده می‌کنیم.</p><p>این روش بهبودی نسبت به رویکرد اول است، زیرا در این روش ما هر زمان که از <code>props </code>استفاده می‌کنیم، <code>props </code>را تکرار نمی‌کنیم.</p><p>در ادامه، مثالی از تخریب <code>props </code>آمده است. در قطعه کد ابتدایی، ما <code>type، placeholder، name</code> و <code>changeHandler </code>را از <code>props </code>به عنوان اولین مورد در کامپوننت دریافت می‌کنیم.</p><p> </p><pre><code class="language-javascript">const { type, placeholder, name, changeHandler } = props</code></pre><p> </p><p>در مثال کد زیر، می‌توانیم بهبود در کد را مشاهده کنیم. ما کامپوننت <code>Input </code>را با <code>props </code>داریم، اما به جای تکرار <code>props.name</code>، ما <code>props </code>را تخریب می‌کنیم. این بهبود بزرگی در خوانایی و تجربه توسعه‌دهنده دارد.</p><p> </p><pre><code class="language-javascript">const Input = (props) => { const { type, placeholder, name, changeHandler } = props; return <input type={type} placeholder={placeholder} name={name} className="block p-2 my-2 text-black" onChange={changeHandler}/> }</code></pre><p> </p><h3><span style="font-size:22px;"><span style="-webkit-text-stroke-width:0px;display:inline !important;float:none;font-style:normal;font-variant-caps:normal;font-variant-ligatures:normal;font-weight:400;letter-spacing:normal;orphans:2;text-align:start;text-decoration-color:initial;text-decoration-style:initial;text-decoration-thickness:initial;text-indent:0px;text-transform:none;white-space:pre-wrap;widows:2;word-spacing:0px;"><strong>چگونگی تخریب (Destructuring) props در آرگومان‌های کامپوننت:</strong></span></span></h3><p> </p><p>این روش تخریب <code>props </code>مورد علاقه من است. توسعه‌دهندگان می‌توانند در ابتدای کامپوننت ببینند که کدام <code>props </code>در کامپوننت استفاده می‌شود. همچنین هیچ تکراری از کلمات کلیدی props نداریم.</p><p>نسبت به رویکرد قبلی، این روش:</p><p><span style="font-size:18px;">- خشک (Don't Repeat Yourself - DRY) است: ما <code>props </code>را تکرار نمی‌کنیم.</span><br><span style="font-size:18px;">- قابل خواندن است: در خط اول (تعریف) کامپوننت، می‌دانیم که کدام <code>props </code>را انتظار دارد. این باعث بهبود خوانایی و وضوح کامپوننت می‌شود.</span></p><p><span style="font-size:18px;">در کد زیر، می‌بینیم که ما در تعریف کامپوننت <code>props </code>را تخریب کرده‌ایم. این باعث بهبود خوانایی می‌شود. چرا که توسعه‌دهندگان می‌توانند به خط اول نگاه کنند و بفهمند که در این کامپوننت چند و چه <code>props </code>انتظار دارد.</span></p><p> </p><pre><code class="language-javascript">const Input = ({ type, placeholder, name, changeHandler }) => { return <input type={type} placeholder={placeholder} name={name} className="block p-2 my-2 text-black" onChange={changeHandler}/> }</code></pre><p> </p><h2><span style="font-size:35px;"><strong>4- یک فایل برای هر کامپوننت داشته باشید</strong></span></h2><p> </p><p>در <strong>ReactJS</strong>، داشتن یک فایل برای هر کامپوننت مهم است. این کمک می‌کند کد شما تمیزتر و قابل نگهداری‌تر باشد.</p><p>همچنین این اصل مسئولیت تکی را که قبلاً اشاره کردم، رعایت می‌کند.</p><p>جلبکننده است که یک فایل داشته باشیم و تمام کد را در داخل آن بنویسیم تا از عزل متغیرها و کدها استفاده کنیم - اما باید آن را به کامپوننت‌های کوچکتر تقسیم کنیم.</p><p>در مثال زیر، ما یک فایل به نام <code>Input.jsx</code> داریم که دارای دو کامپوننت <code>Input </code>و <code>Icon </code>است. ما از <code>Icon </code>در بخش بازگشتی (<code>return</code>) <code>Input </code>استفاده می‌کنیم.</p><p>به نظر می‌رسد که <code>Input </code>و <code>Icon </code>مرتبط هستند و منطقی است که آنها را در یک فایل گروه‌بندی کنیم. اما نباید این کار را انجام دهیم، زیرا این یک راه‌حل قابل توسعه نیست (و همچنین قابل استفاده مجدد نیز نیست).</p><p> </p><pre><code class="language-javascript">// Don't do this: import React from 'react'; // File name: Input.jsx // This example shows how we are exporting 2 components from one file // We should NOT do this const Input = ({ type, placeholder, name, changeHandler }) => { return <> <input type={type} placeholder={placeholder} name={name} className="block p-2 my-2 text-black" onChange={changeHandler}/>

<Icon type="warning"/> } <> const Icon = ({ type, url}) => { return <img src={url} data-type={type} /> } export {Input, Icon};</code></pre><p> </p><p>به جای اینکه باید دو کامپوننت مجزا برای <code>Input </code>و <code>Icon </code>بسازیم، مانند مثال زیر نشان داده شده است. این به شما کمک می‌کند تا هر دو کامپوننت را مجدداً استفاده کنید و آنها را به صورت مستقل ارتقا دهید.</p><p> </p><pre><code class="language-javascript">// Do this instead: // Input.jsx: create 2 separate files for Input and InputIcon import React from 'react'; const Input = ({ type, placeholder, name, changeHandler }) => { return <input type={type} placeholder={placeholder} name={name} className="block p-2 my-2 text-black" onChange={changeHandler}/> } export default Input;</code></pre><p> </p><h2><span style="font-size:35px;"><strong>5- از توابع درون‌خط استفاده نکنید</strong></span></h2><p> </p><p>نوشتن توابع درون‌خط در جاوااسکریپت رایج است، اما بهتر است در صورت امکان از افزودن آنها خودداری کنید.</p><p>باید JSX خود را جدا از کد منطقی خود نگه دارید. توابع درون‌خط قابل استفاده مجدد نیستند، به انتزاع کد کمک نمی‌کنند و سختی در آزمون دارند.</p><p>به همین دلیل همیشه باید از توابع درون‌خط خودداری کنید.</p><p>در قطعه کد زیر، ما تابع <code>handleIncrement </code>را به عنوان یک تابع درون‌خط در <code>button </code>داریم. این قابل استفاده مجدد نیست و به صورت تنگاتنگ با کامپوننت ارتباط دارد:</p><p> </p><pre><code class="language-javascript">// Don't do this: import React, { useState } from 'react'; function CounterInline() { const [count, setCount] = useState(0); const handleIncrement = () => { setCount(count + 1); }; return ( <div> <p>Count: {count}</p> <button onClick={handleIncrement}>Increment</button> </div> ); } export default CounterInline;</code></pre><p> </p><p>پس چگونه می‌توانیم از توابع درون‌خط فاصله بگیریم؟ بیایید به نحوه بازنویسی کد بالا نگاهی بیاندازیم.</p><p>در قطعه کد زیر، می‌توانیم <code>incrementCount </code>را در <code>Button </code>استفاده کنیم و انتظار دارد دو آرگومان دریافت کند. ما اینجا تابع را قابل استفاده مجدد کرده‌ایم:</p><p> </p><pre><code class="language-javascript">// Do this instead: import React, { useState } from 'react'; // Standalone function for incrementing function incrementCount(currentCount, setCount) { setCount(currentCount + 1); } const CounterStandalone = () => { const [count, setCount] = useState(0); return ( <div> <p>Count: {count}</p> <button onClick={() => incrementCount(count, setCount)}>Increment</button> </div> ); } export default CounterStandalone; </code></pre><p> </p><h2><span style="font-size:35px;"><strong>6- پیاده‌سازی یک کامپوننت 404 و مسیر (Route)</strong></span></h2><p> </p><p><span style="font-size:18px;">در حین پیاده‌سازی مسیردهی در ReactJS، باید یک کامپوننت 404 اضافه کنیم.</span></p><p><span style="font-size:18px;">زمانی که کاربر تلاش می‌کند تا به یک صفحه دسترسی پیدا کند که وجود ندارد، کد وضعیتی که از سمت سرور برگشت داده می‌شود 404 خواهد بود. به عنوان یک توسعه‌دهنده جلویی، ایده‌ی خوبی است که به کاربر پیام خطا نمایش داده شود تا برای او متناسب با موقعیت شرایطی فراهم شود.</span></p><p><span style="font-size:18px;">React-router راهی آسان برای نمایش خطا وقتی که سرور کد وضعیت 404 را برمی‌گرداند، فراهم می‌کند. شما باید یک کامپوننت ایجاد کنید که باید وقتی کد وضعیت 404 از سمت سرور برمی‌گردد، نمایش داده شود.</span></p><p><span style="font-size:18px;">هر زمان که یک کاربر یک مسیر را تایپ کند یا به یک مسیری که وجود ندارد برسد، صفحه 404 پیام خطا را به کاربر نمایش می‌دهد که تجربه کاربری بهتری است (تا فقط مشاهده "404" بدون توضیحی نامفهوم).</span></p><p><span style="font-size:18px;">نکته: در کامپوننت، یک پیوند به صفحه اصلی وب‌سایت خود اضافه کنید. این به کاربر کمک می‌کند تا به صفحه اصلی وب‌سایت شما هدایت شود.</span></p><p> </p><pre><code class="language-javascript"><route path="" component={<Error404/>} /></code></pre><p> </p><h2><span style="font-size:35px;"><strong>7- به تدریج داده‌ها را دریافت کنید</strong></span></h2><p> </p><p><span style="font-size:18px;">در برنامه‌های React، اغلب داده‌ها را از طریق API‌ها دریافت می‌کنید.</span></p><p><span style="font-size:18px;">به جای دریافت داده و ایجاد رابط کاربری به یکباره، باید داده‌ها را درخواستی دریافت کنیم - به عنوان مثال، هنگام پیمایش به دید، هنگام کلیک بر روی صفحه‌بندی، و غیره.</span></p><p><span style="font-size:18px;">این عملکرد برنامه را بهبود می‌بخشد و تجربه کاربری را بهبود می‌بخشد.</span></p><p><span style="font-size:18px;">چندین بسته وجود دارد که می‌توانند به شما در پیاده‌سازی بارگذاری تنبل (lazy loading) کمک کنند. بارگذاری تنبل یک تکنیک است که می‌توانید از آن برای بارگذاری داده‌ها به صورت درخواستی یا به تدریج به صورت لازم استفاده کنید. به جای نمایش تمام داده‌های API در یک زمان روی صفحه، فقط داده‌های مورد نیاز را نمایش می‌دهد.</span></p><p><span style="font-size:18px;">اینجا چگونگی نصب بسته <code>react-lazyload</code> را می‌بینید:</span></p><p> </p><pre><code class="language-javascript">// install react-lazyload package npm install react-lazyload</code></pre><p> </p><p><span style="font-size:18px;">و در اینجا کد آن است:</span></p><p> </p><pre><code class="language-javascript">// Create a component - ItemList.jsx import React, { useState, useEffect } from 'react'; import axios from 'axios'; const ItemList = () => { const [items, setItems] = useState([]); useEffect(() => { // Fetch data from your API here axios.get('https://example.com/api/items') .then(response => { setItems(response.data); }) .catch(error => { console.error('Error fetching data:', error); }); }, []); return ( <div> <h2>Item List</h2> <ul> {items.map(item => ( <li key={item.id}> {item.name} </li> ))} </ul> </div> ); }; export default ItemList; </code></pre><p> </p><p> </p><pre><code class="language-javascript">// App.js import React, { lazy, Suspense } from 'react'; import LazyLoad from 'react-lazyload'; // Import the lazy-loaded component const ItemList = lazy(() => import('./ItemList')); function App() { return ( <div> <h1>React LazyLoad with API Data Example</h1> {/ Use React LazyLoad to lazy-load the component /} <LazyLoad height={200}> <Suspense fallback={<div>Loading...</div>}> <ItemList /> </Suspense> </LazyLoad> </div> ); } export default App;</code></pre><p> </p><p>در مثال کد بالا، یک کامپوننت ایجاد کرده‌ایم که درخواست‌های API را انجام داده و داده‌های API را به صورت <code>ItemList.jsx</code> رندر می‌کند. هنگام استفاده از <code>ItemList </code>در <code>App</code>، به جای نمایش کل داده به یکباره، از <code>LazLoad </code>برای بارگذاری کامپوننت استفاده می‌کنیم.</p><p>به عبارت دیگر، کامپوننت به صورت تنبل بارگذاری می‌شود زمانی که به نزدیکی دیدپذیر شدن در ویوپورت می‌آید و داده‌ها از API نمایش داده می‌شوند.</p><p>بعضی از بسته‌هایی که می‌توانید برای بارگذاری تنبل از آنها استفاده کنید عبارتند از: <code>react-lazyload</code>، <code>react-infinite-scroll-component</code> و <code>react-paginate</code>.</p><p> </p><h2><span style="font-size:35px;"><strong>8- استفاده از مقادیر منحصر به فرد برای ویژگی‌های کلیدی</strong></span></h2><p> </p><p><span style="font-size:18px;">یکی از دلایل محبوبیت React به خاطر "DOM مجازی" آن است.</span></p><p><span style="font-size:18px;">DOM مجازی (VDOM) به شما کمک می‌کند فرآیند به‌روزرسانی رابط کاربری را بهینه‌سازی کنید.</span></p><p><span style="font-size:18px;">React تنها گره‌هایی را به‌روزرسانی می‌کند که تغییر کرده‌اند و به جای تمام DOM کل، این کار را انجام نمی‌دهد مگر اینکه لازم باشد. این یکی از رازهای برنامه‌های با عملکرد برتر است.</span></p><p><span style="font-size:18px;">React نیاز به ویژگی <code>key </code>دارد تا تشخیص دهد تغییر در کدام گره اتفاق افتاده است. به همین دلیل همیشه باید از یک مقدار منحصر به فرد برای <code>key </code>استفاده کنیم.</span></p><p><span style="font-size:18px;">یک مثال خوب از چگونگی انجام این کار، افزودن شناسه (<code>id</code>) به هر مورد است.</span></p><p><span style="font-size:18px;">توجه: از شاخص (index) به عنوان کلید تنها زمانی استفاده کنید که داده‌های شما ثابت (static) باشند و تغییر ترتیب یا فیلتر نشوند.</span></p><p> </p><pre><code class="language-javascript">// List.jsx import React from 'react'; const List = ({ items }) => ( return(<ul> {items.map((item, index) => ( <li key={index}>{item}</li> ))} </ul>) ); export default List;</code></pre><p> </p><pre><code class="language-javascript">// App.jsx import List from './List'; const App = () => { const items = ['Item 1', 'Item 2', 'Item 3', 'Item 4', 'Item 5']; return ( <div> <h1>Simple List Example</h1> <List items={items} /> </div> ); }; export default App;</code></pre><p> </p><p>در مثال کد بالا، ما با استفاده از تابع map روی داده‌ها یک لیست ایجاد می‌کنیم. در کامپوننت <code>List</code>، ما شاخص (<code>index</code>) را به ویژگی کلیدی (<code>key</code>) اختصاص می‌دهیم. این ویژگی به طور پنهانی توسط ReactJS استفاده می‌شود تا هنگامی که هر <code>li </code>اصلاح یا تغییر پیدا کند، عملکرد را بهینه‌سازی کند.</p><p> </p><h2><span style="font-size:35px;"><strong>9- استفاده از انواع (Types)</strong></span></h2><p> </p><p><span style="font-size:18px;">استفاده از ابزارهای دارای بررسی نوع استاتیک (مانند TypeScript) می‌تواند به شما کمک کند تا از وقوع اشکالات غیرضروری در کدتان جلوگیری کنید.</span></p><p><span style="font-size:18px;">همچنین کد شما را با کیفیت و بررسی نوعی پشتیبانی خواهد کرد.</span></p><p><span style="font-size:18px;">اگر کسی هستید که به تازگی شروع به یادگیری در مورد بررسی نوع می‌کنید، می‌توانید با <code>proptypes</code> شروع کنید و در آینده TypeScript را یاد بگیرید.</span></p><p><span style="font-size:18px;">جاوااسکریپت از نوع مشخص (strictly typed) پیروی نمی‌کند، به این معنا که احتمال وقوع اشکالات غیرمنتظره یا خطاهای نوعی بیشتر است.</span></p><p><span style="font-size:18px;">به عنوان مثال، وقتی انتظار داریم یک prop یک عدد باشد، ممکن است به عنوان یک رشته دریافت شود که باعث خطا می‌شود.</span></p><p><span style="font-size:18px;">بنابراین، نوع‌های دقیق و TypeScript می‌توانند به شما کمک کنند تا از وقوع چنین اشکالات غیرمنتظره‌ای در طول توسعه جلوگیری کنید.</span></p><p> </p><pre><code class="language-javascript">import React from 'react'; import PropTypes from 'prop-types'; const UserCard = ({ name, age, email }) => { return ( <div> <h2>User Card</h2> <p>Name: {name}</p> <p>Age: {age}</p> <p>Email: {email}</p> </div> ); }; // Define the prop types for the UserCard component UserCard.propTypes = { name: PropTypes.string.isRequired, // A required string prop age: PropTypes.number.isRequired, // A required number prop email: PropTypes.string, // An optional string prop };</code></pre><p> </p><pre><code class="language-javascript">import UserCard from 'userCard'; const App = () => { return ( <div> <h1>PropTypes Example</h1> <UserCard name="John Doe" age={30} email="john@example.com" /> </div> ); }; export default App;</code></pre><p> </p><p>در مثال کد بالا، ما یک کامپوننت به نام <code>UserCard </code>ایجاد کرده‌ایم. این کامپوننت انتظار دارد که 3 ویژگی (prop) به نام‌های name، age و email دریافت کند. با استفاده از <code>proptypes</code>، ما دو مورد برای ویژگی‌ها اعلام می‌کنیم - نوع داده (نوع داده‌ای که ویژگی‌ها باید داشته باشند، مانند رشته، عدد و غیره) و اینکه ویژگی اجباری یا اختیاری است.</p><p>در هنگام استفاده از کامپوننت <code>UserCard</code>، اگر کسی نوع داده اشتباهی را ارسال کند یا یک ویژگی اجباری را از دست بدهد، کد خطا ایجاد خواهد شد و به او اخطار داده می‌شود تا آن را تصحیح کند.</p><p> </p><h2><span style="font-size:35px;"><strong>10- استفاده از توابع </strong><code><strong>lazy()</strong></code><strong> و </strong><code><strong>Suspense()</strong></code></span></h2><p> </p><p><span style="font-size:18px;">ReactJS از بسته‌بندی‌کننده Webpack (اگر از creat-react-app استفاده می‌کنید) استفاده می‌کند.</span></p><p><span style="font-size:18px;">Webpack مسائل مربوط به بسته‌بندی کد را در اختیار دارد و عملیاتی مانند شیک‌تر کردن درخت (tree shaking) را انجام می‌دهد.</span></p><p><span style="font-size:18px;">اما روش کار React این است که حتی اگر به آن نیاز نداشته باشیم، کل کد را در سمت مشتری دانلود می‌کند. این یک وظیفه گران‌قیمت است. اگر اندازه بسته شما بزرگ باشد، عملکرد برنامه‌های شما را تحت تاثیر قرار می‌دهد.</span></p><p><span style="font-size:18px;">یک راه خوب برای جلوگیری از این امر، بارگذاری تنبل (lazy loading) کد درخواستی با استفاده از <code>lazy()</code> است، که به مسیرها اجازه می‌دهد زمانی که نیاز دارند بارگذاری شوند.</span></p><p> </p><pre><code class="language-javascript">const LazyComponent = lazy(() => import('./LazyComponent'));</code></pre><p> </p><p><span style="font-size:18px;">در هنگام استفاده از <code>lazy()</code> باید نیز از Suspense() استفاده کنیم، زیرا <code>lazy()</code> یک راه همزمان برای بارگذاری کامپوننت‌ها است.</span></p><p><span style="font-size:18px;">ما نمی‌خواهیم تا زمانی که مسیر ما بارگذاری نشده است، به کاربر یک صفحه خالی نمایش دهیم. <code>Suspense()</code> با نمایش یک پیام در حین بارگذاری کامپوننت به کمک می‌آید.</span></p><p> </p><pre><code class="language-javascript"> <Suspense fallback={<div>Loading...</div>}> {/ The LazyComponent will only be loaded when needed */} <LazyComponent /> </Suspense></code></pre><p> </p><p> </p><h2><span style="color:hsl(270,75%,60%);font-size:35px;"><strong>جمع بندی</strong></span></h2><p> </p><p><strong>به پایان رسیدیم. این نکات نه تنها مختص کد‌های بزرگ نیستند بلکه برای پروژه‌های هر اندازه‌ای مناسب هستند.</strong></p><p> </p><p><strong>در سطح بالا ما در مورد مفاهیم زیر آموختیم:</strong></p><p> </p><p><strong>- پیروی از اصل DRY</strong><br><strong>- پیروی از اصل مسئولیت تکی</strong><br><strong>- ایجاد تجربه کاربری خوب با بارگذاری تدریجی داده‌ها</strong><br><strong>- بهبود قابلیت خوانایی کد</strong><br><strong>- بهبود تجربه توسعه‌دهنده</strong><br><strong>- جلوگیری از اشکالات در زمان توسعه</strong><br><strong>- بهبود عملکرد</strong></p><p> </p><p><strong>موفق باشید!</strong></p>

#react #reactjs #javascript #js #developer #improve #develop