چگونه قسمت های سخت React را یاد بگیریم – و نکاتی برای غلبه بر آنها
آیا یادگیری React را شروع کرده اید، فقط برای مواجهه با اشکالاتی که باعث شد به فکر شغلی در گله داری بز باشید؟ نگران نباشید - همه ما آنجا بوده ایم.
در این راهنما، به من در تلاشی از طریق شگفتیهای عجیب React میپیوندید. من به شما کمک میکنم در لحظات گیجکننده پیمایش کنید و اطمینان حاصل کنم که هرگز نباید از خود بپرسید: "React چه خبر است؟"
چه یک ماجراجوی باتجربه React باشید و چه در حال کشف رمز و راز DOM های مجازی، نترسید. من اینجا هستم تا داستانهای مبارزات اولیهام را به اشتراک بگذارم، باگهای مرموز را رفع کنم و راه را برای سفری هموارتر هموار کنم.
پیش نیازها
مبانی HTML و CSS
مبانی ES6 JavaScript و React
آنچه را پوشش خواهیم داد:
خلاصه سریع React Fundamentals
-اجزاء: بلوک های ساختمان وب
– JSX: جایی که HTML با جاوا اسکریپت ملاقات می کند
- حالت و لوازم: دوتایی پویا
قسمت های خوب، بد و چالش برانگیز React
- قسمت های خوب React
- قسمت های بد React
- قسمت های چالش برانگیز React
- اشتباهات کلیدی
- حالت های جهش یافته به طور مستقیم
- اشکالات مرموز با رندر شرطی
- نادیده گرفتن آرایه های وابستگی در React Hooks
- نادیده گرفتن زنجیرهسازی اختیاری برای دادههای API
- نادیده گرفتن React Fragments برای گروه بندی عناصر JSX
پایان دادن به سفر عجیب و غریب با React
خلاصه سریع React Fundamentals
کتابخانه React حول 3 بلوک ساختمانی می چرخد: Components، JSX، و State & Props.
مولفه ها: بلوک های وب
اجزاء را به عنوان آجرهای LEGO رابط کاربری خود تصور کنید - یک قطعه واحد و قابل استفاده مجدد که به ساختار بزرگ کمک می کند. آنها عملکرد، استایل و رفتار را در بر می گیرند و رابط کاربری شما را هم ماژولار و هم مقیاس پذیر می کنند.
از یک دکمه ساده تا یک نوار کناری پیچیده، کامپوننتها قلب و روح توسعه React هستند.
JSX: جایی که HTML با جاوا اسکریپت ملاقات می کند
JSX یا JavaScript XML ممکن است در ابتدا ترکیبی عجیب از HTML و JavaScript به نظر برسد، اما کاملاً ساده است. این سس مخفی است که سینتکس React را بسیار رسا و پویا می کند.
با JSX، اجزای UI خود را با استفاده از نحوی می نویسید که شبیه HTML است، اما زیر آن، جاوا اسکریپت خالص است.
وضعیت و لوازم: دوتایی پویا
دوتایی پویا از حالت و پروپوزال به صفحات React جان می بخشند زیرا تعاملی را به برنامه های وب شما اضافه می کنند.
وضعیت: اعطای حافظه به اجزا
State حافظه را برای اجزا فراهم می کند و به آنها امکان می دهد رویدادهای گذشته را به خاطر بسپارند و رفتار خود را در طول زمان تغییر دهند. این کلید پاسخگو و پویا بودن رابط کاربری شما است.
فرمی را تصور کنید که ورودی کاربر را به خاطر می آورد یا شمارنده ای که با هر کلیک افزایش می یابد. این جادوی دولت است.
امکانات: فعال کردن ارتباطات
Props (مخفف خواص) ارتباط بین اجزا را تسهیل می کند. آنها به اجزای والد اجازه می دهند تا داده ها را به فرزندان خود منتقل کنند و جریان یکپارچه اطلاعات را ایجاد کنند.
ابزارها را به عنوان پیام رسان در نظر بگیرید و اطمینان حاصل کنید که هر جزء نقش خود را می شناسد و اطلاعات لازم را برای انجام آن دریافت می کند.
قسمت های خوب، بد و گیج کننده React
قبل از اینکه به جنبههای گیجکننده React بپردازیم، ضروری است که به گنجینههایی که React را به یک قهرمان واقعی در زرادخانه شما تبدیل میکنند، توجه کنید.
بخش های خوب React
DOM مجازی و مزایای آن
DOM مجازی یک مفهوم انقلابی است که به React سرعت و کارایی می دهد.
هنگامی که تغییراتی در برنامه شما رخ می دهد، React بلافاصله DOM واقعی را به روز نمی کند. درعوض، با یک کپی سبک، Virtual DOM کار میکند که حداقل تنظیمات را به سرعت رعد و برق انجام میدهد. این نه تنها عملکرد را بهینه می کند، بلکه تجربه کاربری روان تری را نیز ارائه می دهد.
ReactDOM.createRoot(document.getElementById("root")).render( <App /> );
این فرآیند از الگوریتم تفاوت React در DOM مجازی استفاده می کند. حداقل مجموعه تغییرات مورد نیاز در DOM واقعی را شناسایی می کند تا وضعیت به روز شده را منعکس کند.
قطعات قابل استفاده مجدد
در React، اصل راهنما قابلیت استفاده مجدد است. کامپوننت ها، بلوک های ساختمانی اساسی که در بالا مورد بحث قرار گرفتیم، می توانند در برنامه شما ساخته و به کار گرفته شوند. این نه تنها ساختار کد مدولار و سازمان یافته را تقویت می کند، بلکه شما را از بار اختراع مجدد چرخ رها می کند.
// Reusable Button Component const Button = ({ label, onClick }) => ( <button onClick={onClick}>{label}</button> ); // Usage <Button label="Click me" onClick={() => console.log("Button Clicked")} />
اتصال داده یک طرفه برای یک جریان قابل پیش بینی
React یک جریان داده یک طرفه را اعمال می کند و از قابلیت پیش بینی و نگهداری اطمینان می دهد.
اجزای والد داده ها را از طریق لوازم جانبی به فرزندان خود منتقل می کنند و هر گونه تغییر توسط مؤلفه والد نظارت می شود. این خیابان یک طرفه از هرج و مرج با اتصال داده های دو طرفه که در چارچوب های دیگر دیده می شود جلوگیری می کند.
const ParentComponent = () => { const [data, setData] = useState("Hello from Parent!"); return <ChildComponent data={data} />; }; const ChildComponent = ({ data }) => <div>{data}</div>;
قسمت های بد React
هر چند بخش هایی از React وجود دارد که ایده آل نیستند. اکنون به طور خلاصه آنها را مرور می کنیم تا بتوانید از آنها آگاه شوید.
منحنی یادگیری شیب دار برای مبتدیان
شروع با React می تواند سخت باشد، به خصوص اگر در توسعه وب تازه کار هستید. مفاهیمی مانند JSX، کامپوننت ها و مدیریت حالت ممکن است مانند یک پیچ و خم به نظر برسند. اما نگران نباشید! با کمی تمرین و حوصله، کار آسان تر می شود و React آشناتر می شود.
JSX ممکن است در ابتدا شما را متحیر کند
JSX، ترکیب ویژه HTML و جاوا اسکریپت، در ابتدا می تواند کمی گیج کننده باشد. مثل یادگیری یک زبان جدید است که این دو را با هم ترکیب می کند. اما همانطور که از آن استفاده می کنید، خواهید دید که چگونه کد شما را کوتاه تر و واضح تر می کند.
چالش های مدیریت دولتی
استفاده از حالت در React قدرتمند است، اما همچنین می تواند مشکل ساز باشد. مدیریت وضعیت در بسیاری از قطعات مختلف، به ویژه در پروژه های بزرگ، می تواند تنظیمات پیچیده و مشکلات احتمالی ایجاد کند. خوشبختانه، ابزارهایی مانند Redux برای کمک به مدیریت این پیچیدگی وجود دارد.
بخش های چالش برانگیز React
اشتباهات کلیدی
هنگام ساخت برنامه های خود، ممکن است اغلب عناصر تکراری داشته باشید که اطلاعات مشابهی را نشان می دهند یا سبک های مشابهی را به اشتراک می گذارند. مرحله منطقی این است که روی آنها حلقه بزنید تا فهرست ی از عناصر ایجاد شود.
function ListComponent() { const people = [{ name: "Mitchelle" }, { name: "July" }, { name: "David" }]; return ( <ul> {/ Looping over the people array to create list items /} {people.map((person) => ( <li>{person.name}</li> ))} </ul> ); }
همه چیز خوب به نظر می رسد تا زمانی که متوجه هشداری در کنسول خود یا بدتر از آن، رفتار عجیب و غریب در نحوه ارائه فهرست خود شوید.
React از کلیدها برای به روز رسانی و ترتیب مجدد عناصر در یک فهرست استفاده می کند. هنگامی که فراموش می کنید یک پایه کلید ارائه کنید یا اگر کلیدها منحصر به فرد نیستند، React کمی گم می شود. این مانند تلاش برای پیگیری موارد موجود در آرایه بدون هیچ شناسه خاصی است - همه چیز با هم مخلوط می شود و ممکن است در UI خود با باگ های غیرمنتظره مواجه شوید.
چگونه آن را حل کنیم
اولین غریزه بسیاری از توسعه دهندگان در هنگام ایجاد فهرست های پویا، استفاده از ویژگی index به عنوان کلید است. به نظر می رسد راه حل مناسبی باشد، زیرا ایندکس یک شناسه منحصر به فرد برای هر عنصر در آرایه ارائه می دهد - اما به دلایل زیر بهترین روش نیست:
Non-Persistent : اگر ترتیب یا تعداد آیتم ها تغییر کند، React ممکن است گیج شود. به عنوان مثال، اگر یک مورد از ابتدای فهرست اضافه یا حذف شود، همه شاخص های بعدی تغییر می کنند و باعث بروز مشکلات احتمالی در رندر مجدد می شوند.
جهش آرایه ها : عملیات هایی مانند مرتب سازی یا فیلتر کردن می توانند ترتیب آیتم ها را تغییر دهند و ارتباط بین شاخص و آیتم واقعی را از بین ببرند.
نگرانی های عملکرد : React برای به روز رسانی های کارآمد به کلیدها متکی است. استفاده از ایندکس بهعنوان یک کلید ممکن است بر عملکرد هنگام برخورد با فهرست های بزرگ یا بهروزرسانیهای مکرر تأثیر بگذارد.
برخی از جایگزین های بهتر عبارتند از:
از یک شناسه منحصر به فرد استفاده کنید : اگر هر آیتم در آرایه شما یک شناسه منحصر به فرد دارد، مانند یک ویژگی id
، از آن به عنوان کلید استفاده کنید.
{people.map((person) => ( <li key={person.id}>{person.name}</li> ))}
ایجاد یک کلید منحصر به فرد: در مواردی که موارد فاقد یک شناسه منحصر به فرد طبیعی هستند، از تابعی مانند crypto.randomUUID()
برای تولید یک کلید منحصر به فرد استفاده کنید.
{people.map((person) => ( <li key={crypto.randomUUID()}>{person.name}</li> ))}
با انتخاب یکی از این گزینهها، کلیدهای ثابت و منحصربهفردی را در اختیار React قرار میدهید که به مدیریت و بهروزرسانی فهرستهای پویا کمک میکند.
توجه : ممکن است فکر کنید "اگر crypto.randomUUID
یک شناسه منحصربفرد تولید کند، ( Math.random()
*عدد بزرگ) به همین صورت عمل می کند، درست است؟
Math.random()
نیز می تواند به عنوان یک کلید کافی باشد، اما ایده بدی است زیرا کلیدهای تولید شده در رندرهای مجدد پایدار نخواهند بود، که منجر به مشکلات بالقوه عملکرد و ناسازگاری های رندر می شود.
کشورهای در حال جهش مستقیم
تصور کنید که روی کامپوننتی کار می کنید که مجموعه ای از نام ها را مدیریت می کند. به جای استفاده از روش تنظیم کننده مناسب برای به روز رسانی حالت، تصمیم می گیرید مستقیماً حالت را تغییر دهید.
const MutableStateComponent = () => { const [names, setNames] = useState(["David", "John", "Steph", "Anthony"]); const removeLastName = () => { console.log(names); // Direct mutation of state using pop() names.pop(); setNames(names); // This won't trigger a re-render }; return ( <div> <p>Names: {names.join(", ")}</p> <button onClick={removeLastName}>Remove Last Name</button> </div> ); };
در کمال تعجب، رابط کاربری آنطور که انتظار میرفت بهروزرسانی نمیشود، و در سناریویی گیر افتادهاید که فهرست نامها ثابت به نظر میرسد. اشتباه نکنید، آرایه همانطور که در زیر مشاهده می کنید به روز می شود:
مشکل چیست؟
React برای بهروزرسانیهای کارآمد به یک وضعیت تغییرناپذیر متکی است و هنگامی که این مکانیسم را دور میزنید، جریان دادههای یک جهته را مختل میکند.
در این حالت، استفاده از pop()
آرایه اصلی را در جای خود جهش می دهد و React مسیر تغییرات را از دست می دهد. این منجر به ارائه نادرست مولفه می شود.
چگونه آن را حل کنیم
برای اطمینان از اینکه کامپوننت شما مطابق انتظار رفتار می کند و از اصول React پیروی می کند، همیشه از تابع تنظیم کننده ( setNames
) برای به روز رسانی وضعیت استفاده کنید.
const MutableStateComponent = () => { const [names, setNames] = useState(["David", "John", "Steph", "Anthony"]); const removeLastName = () => { // Use setNames to update state setNames((prevNames) => prevNames.slice(0, -1)); console.log(names); }; return ( <div> <p>Names: {names.join(", ")}</p> <button onClick={removeLastName}>Remove Last Name</button> </div> ); };
با استفاده از setNames
و ایجاد یک آرایه جدید با تغییرات مورد نظر (در این مورد، با استفاده از slice
برای حذف آخرین عنصر)، اطمینان حاصل می کنید که React می تواند وضعیت را به طور دقیق ردیابی و به روز کند و در نتیجه رفتار UI مورد انتظار را ایجاد می کند.
اشکالات مرموز با رندر شرطی
رندر شرطی، اگرچه قدرتمند است، اما در صورت عدم رسیدگی دقیق، می تواند اشکالات ظریفی را ایجاد کند. درک تلههای رایج، بهویژه آنهایی که مربوط به ارزیابیهای درستی و نادرست هستند، برای جلوگیری از رفتار رندر مرموز بسیار مهم است.
به مثال زیر توجه کنید:
const IncorrectConditionalComponent = ({ showContent }) => ( {showContent && <div>Show me if true!</div>} );
اشکال: رندر غیرمنتظره با مقادیر نادرست
در این قطعه کد، اگر showContent
یک مقدار نادرست باشد، مانند 0
، کامپوننت یک نتیجه غیرمنتظره ارائه می دهد. بهجای اینکه محتوا را بهخوبی رندر نکند، به دلیل درج مستقیم بریسهای فرفری، 0
روی صفحه نمایش میدهد.
مشکل چیست؟
مسئله در سوء مدیریت ارزش های حق و باطل است. استفاده مستقیم از بریسهای فرفری یک شیء پوشش ( [object Object]
) ایجاد میکند که باعث میشود کامپوننت هر مقدار موجود را ارائه کند، حتی اگر نادرست باشد.
چگونه آن را حل کنیم
برای پیدا کردن اشکالات رندر مربوط به مقادیر درستی و نادرست، از تحلیل شرطی صریح تر استفاده کنید.
const CorrectConditionalComponent = ({ showContent }) => ( showContent ? <div>Show me if true!</div> : null );
در این نسخه تصحیح شده، اپراتور سه تایی از تحلیل دقیق صحت اطمینان حاصل می کند و از مشکلات رندر غیرمنتظره جلوگیری می کند. با مدیریت صریح ارزشهای درستی و نادرست، اجزای قوی میسازید که در سناریوهای مختلف رفتار قابل پیشبینی دارند.
نادیده گرفتن آرایه های وابستگی در React Hooks
تصور کنید روی یک مؤلفه کار میکنید که برای اجرای منطقی به یک اثر متکی است، وقتی یک حالت خاص، مثلاً count
، تغییر میکند. اما با وجود اینکه شما تعداد را افزایش می دهید، به نظر نمی رسد که اثر اجرا شود، و شما در تعجب هستید که چرا منطق شما تاثیر نمی گذارد.
const Counter = () => { const [count, setCount] = useState(0); const handleClick = () => { setCount((count) => count + 1); }; useEffect(() => { console.log("The current count value is ", count); }, []); return ( <div> <p>Count: {count}</p> <button onClick={handleClick}>Increment</button> </div> ); };
مشکل چیست؟
مشکل در نادیده گرفتن آرایه وابستگی در useEffect
شم است. وقتی وابستگیها را حذف میکنید، React ممکن است تشخیص ندهد که اثر به یک حالت خاص مرتبط است و منجر به دادههای قدیمی و رفتار غیرمنتظره میشود.
چگونه آن را حل کنیم
برای بازگرداندن اثر خود به مسیر، وابستگی های مربوطه را در آرایه وابستگی قرار دهید. مانند راهاندازی محرکها است – شما به React میگویید: «هی، هر زمان که این دادههای خاص تغییر کردند، این افکت را اجرا کن».
useEffect(() => { console.log("The current count value is ", count); }, [count]);
که اکنون قلاب useEffect
را فعال می کند:
نادیده گرفتن زنجیرهسازی اختیاری برای دادههای API
شما روی مؤلفه ای کار می کنید که داده های کاربر واکشی شده از یک API را نمایش می دهد. همه چیز خوب به نظر می رسد تا زمانی که با یک خطای زمان اجرا غیر منتظره مواجه شوید. مقصر؟ یک اپراتور زنجیربندی اختیاری گم شده است.
مشکل چیست؟
پاسخ های API می توانند غیرقابل پیش بینی باشند و همه ساختارهای داده با انتظارات شما مطابقت ندارند. نادیده گرفتن زنجیره اختیاری، بهویژه هنگام دسترسی به آپشن های عمیق تو در تو (نگاه کردن به دادههای پاسخ Strapi 👀) میتواند منجر به خطاهای زمان اجرا شود، اگر یک ویژگی تعریف نشده باشد.
چگونه آن را حل کنیم
برای محافظت از مؤلفه خود در برابر خطاهای غیرمنتظره، هنگام دسترسی به ویژگی های تو در تو در داده های API، از زنجیره اختیاری ( ?.
) استفاده کنید.
به عنوان مثال، فرض کنید می خواهید یک ویژگی عمیق تو در تو (برچسب) را از این داده بخوانید:
const data = { id: 1, title: "First Item", content: "Content for the first item", category: { id: 101, name: "Category A", description: "Description of Category A", tags: [ { id: 1001, label: "Tag 1", }, { id: 1002, label: "Tag 2", }, ], }, author: { id: 201, name: "John Doe", email: "john.doe@example.com", }, };
راه صحیح استفاده از زنجیره اختیاری برای بازیابی آن داده است:
const firstLabel = data?.category?.tags?.[0]?.label;
به جای دسترسی مستقیم به آن ویژگی ها:
const firstLabel = data.category.tags[0].label;
در صورت تغییر ساختار داده، این کار از مشاهده خطای صفحه سفید و کنسول flooded جلوگیری می کند. این مانند قرار دادن یک شبکه ایمنی است – اگر ملکی گم شده باشد، برنامه شما به این صورت خراب نمی شود:
نادیده گرفتن React Fragments برای گروه بندی عناصر JSX
هنگام کار با کامپوننتهای React، ممکن است با سناریویی روبرو شوید که میخواهید چندین عنصر JSX را از یک تابع برگردانید، اما با یک خطای نحوی مواجه میشوید.
مشکل چیست؟
این به دلیل محدودیت در جاوا اسکریپت است، زیرا اجازه بازگشت عناصر مجاور را بدون والد مشترک نمی دهد.
کد مشکل ساز زیر را در نظر بگیرید:
function User() { return <div> David Jaja</div> <div>Twitter: https://twitter.com/JajaDavid8</div>; }
این کد منجر به یک خطا می شود: "عناصر JSX مجاور باید در یک برچسب محصور پیچیده شوند."
چگونه آن را حل کنیم
من می دانم که ممکن است به چه چیزی فکر کنید - چرا به سادگی عناصر را در یک div قرار ندهید و ادامه دهید؟
اگرچه این یک راه حل سریع به نظر می رسد، اما یک نقطه ضعف بالقوه را معرفی می کند. با گفت ن یک div، یک عنصر والد غیر ضروری در DOM ایجاد می کنید.
این نشانهگذاری اضافی، اگرچه خطای فوری را برطرف میکند، میتواند منجر به عواقب ناخواستهای مانند تأثیر گذاشتن بر سبکها یا طرحبندی شود و ممکن است با شیوههای کدنویسی بهینه هماهنگ نباشد.
و من مطمئن هستم که شما نمی خواهید به یک "divpocalipse" برسید.
برای غلبه بر خطای نحو و نشانه گذاری غیر ضروری DOM، React یک راه حل بهینه را معرفی کرد: React Fragments.
React Fragments برای رفع نیاز به بازگرداندن چندین عنصر JSX بدون معرفی عناصر والد غیر ضروری در DOM استفاده می شود.
در اینجا نحوه استفاده از React Fragments آورده شده است:
import React from "react"; function User() { return ( <React.Fragment> <div> David Jaja</div> <div>Twitter: https://twitter.com/JajaDavid8</div> </React.Fragment> ); }
یا با استفاده از سینتکس کوتاه:
function User() { return ( <> <div> David Jaja</div> <div>Twitter: https://twitter.com/JajaDavid8</div> </> ); }
با استفاده از React Fragments، کد JSX را تمیز و مختصر بدون وارد کردن عناصر غیر ضروری به DOM حفظ می کنید و خوانایی کد را افزایش می دهید.
رویکردهای نظری برای واکنش
من چند راه مفید برای لذت بخش تر کردن کار با React پیدا کرده ام. به جای قوانین سختگیرانه، به اینها به عنوان انتخاب های شخصی من فکر کنید تا خوانش کد را آسانتر کنم، نحوه عملکرد آن را بهبود ببخشید و مطمئن شوید که در شکل خوبی باقی می ماند.
قرار دادن دادهها در خارج از مؤلفهها : مواردی مانند فهرستها و گروههای اطلاعات را در صورت امکان به خارج از بخش اصلی یک مؤلفه منتقل کنید. این به جلوگیری از بهروزرسانیهای اضافی کمک میکند و مدیریت دادهها را بدون استفاده از توابع خاصی مانند useCallback
سادهتر میکند.
مراقب React.memo
باشید : استفاده از React.memo
میتواند به اجرای بهتر اجزای شما کمک کند، اما همیشه لازم نیست. اگر یک مؤلفه با اطلاعات جدید خیلی تغییر می کند، استفاده از React.memo
ممکن است مفید نباشد. عاقلانه از آن استفاده کنید.
قلابهای React سفارشی خود را ایجاد کنید : من همچنین دوست دارم ابزارهای خاص خود را با قلابهای React سفارشی بسازم. کمی پیشرفته است، اما کمک می کند کد من مرتب و منظم باشد.
پایان دادن به سفر عجیب و غریب با React
سفر React ترکیبی از قایقرانی روان و سواری های ناهموار است. ما قدرت مولفههای قابل استفاده مجدد و DOM مجازی را دیدهایم و با لحظات گیجکنندهای مانند از دست دادن وسایل کلیدی و اشکالات رندر شرطی و غیره مقابله کردهایم.
همانطور که به سفر خود با React ادامه می دهید، ممکن است کد شما تمیز باشد، اجزای شما قابل استفاده مجدد باشند و "What's Up with React؟" لحظه ها تبدیل به "آها!" افشاگری ها کد نویسی مبارک! 🚀
اطلاعات تماس
می خواهید به من وصل شوید یا با من تماس بگیرید؟ در صورت تمایل به من در مورد موارد زیر ضربه بزنید:
توییتر: @jajadavid8
لینکدین: دیوید جاجا
ایمیل: Jajadavidjid@gmail.com
ارسال نظر