<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>نوشته های محسن محمدی رهنما</title><link>https://virgool.ir/feed/@mohammadi.dev91</link><description>دویی از خود بُرون کردم یکی دیدم دوعالم را / یکی جویم، یکی گویم، یکی دانم، یکی خوانم</description><language>fa</language><pubDate>2026-11-10 15:22:24</pubDate><image><url>https://files.virgool.ir/upload/users/1878382/avatar/OxRjG9.jpg</url><title>محسن محمدی رهنما</title><link>https://virgool.ir/@mohammadi.dev91</link></image><item><title>فرق SPA با PWA</title><link>https://virgool.ir/codenevis/فرق-spa-با-pwa-aeycjciyv6tc</link><description>سلام دوستان عزیزم من اومدم با یه مقاله دیگه و امیدوارم حال دل همتون خوب باشه 💐🤗، خب همونطور که از عنوان مقاله مشخصه میخوام براتون از تفاوت بین SPA با PWA براتون صحبت کنم. من توی پست لینکدین خودم از SPA براتون صحبت کردم و پیشنهاد میکنم از این قسمت بهش سر بزنید.خب پس اگه موافق باشید بریم سراغ PWA و مقایسه اون با SPA ، با من همراه باشین 🥳...قدم اول، PWA چیستبزارید قبل از اینکه برم سراغ تعریف اصلی PWA قبلش ذهنتون رو آماده کنم تا فقط یه تعریف تیتر وار از PWA خدمتتون نگفته باشم، سایت freeCodeCamp یه تیتر جالب برای تعریف PWA زده که &#34;These days, everything is made possible with the help of mobile phones and applications&#34; که اگه بخوام تفسیرش کنم براتون منظور اینه که توی دنیا امروزه، شما بنا به هر دلیلی وقتی احتیاج به خدماتی دارید از جمله سفارش غذا، خدمات دولتی و بانکداری ، خرید محصول و... برای همشون به لطف تلفن های همراه تون، Application مربوط به خوده اون خدمات رو دارن و نیازهای شما رو برطرف میکنن. خب همه چی تا اینجای کار گل و بلبل پیش رفت 😁 ولی حالا حساب کنید این قصه برای اون توسعه دهنده های بنده خدا که این App رو نوشتن آنچنان همچین گل و بلبل هم نیست ، چون در برخی مواقع موجب هزینه هایی برای ایجاد و نگهداری اون App میشه که حتی برای تجارت های کوچیک اصلا صرفه اقتصادی و زمانی نداره که شما بیاین یک App برای تلفن همراه ایجاد کنید چه برسه به اینکه از اون App هم نگهداری کنید و پشتیبانی اون رو انجام بدید و...😩خب حالا چاره چیه!🤔اینجاست که دوست خوبمون PWA وارد عمل میشه ، PWA یا به اختصار Progressive Web Application. این رفیقمون  از HTML، CSS و JavaScript ساخته شده (که همتون با این سه تا رفیق دوستداشتنی آشنا هستین 🤗) و پروژه ای که با این تکنولوژی ساخته میشه به ما حس و عملکرد یک برنامه Native رو میده. 🤩  اما منظور از برنامه‌های Native چیست؟ برنامه Native به برنامه هایی میگن که  یک زبان برنامه‌نویسی خاص برای یک پلتفرم دستگاه خاص، یا iOS یا اندروید، ساخته شدن. پروژه هایی که با PWA درست میشن قابلیت‌هایی مانند push notification و قابلیت کار در حالت Offline ساخته میشن. اون‌ها همچنین بر اساس API‌ هایی ساخته شدن و بهبود یافتن که ارائه قابلیت‌هایی از جمله امکان نصب بر روی هر دستگاه را آسون می‌کنه 🤩.  PWA چون داره از اکوسیستم وب  بهره می‌بره (که شامل پلاگین‌ها و تمامی مواردی که برای استقرار و نگهداری یک وب‌سایت شامل میشه) پس اینطوری با یه تیر دو نشون میزنین هم توی پروژه تون وب سایت تون رو گسترش میدید هم خیالتون راحته با صرفه هزینه کم بدون استفاده از زبان برنامه نویسی دیگه ای، app تلفن همراه خودتون رو با بهترین کیفیت گسترش میدید🤩  ، بر عکس یک برنامه Native که توسعه اون بسیار دووشواره😁. این تصویری که مشاهده میکنین آماری هست که سایت visionvix برای PWA منتشر کردهخب حالا فرقش با SPA چیه 🤔حالا بریم سراغ مقایسه PWA و SPA ، هر دو این بزرگواران گزینه های محبوبی برای ساخت برنامه‌های وب مدرن بعمل میان🥳، اما در زمینه عملکرد، امنیت و نگهداری تفاوت دارن. انتخاب مناسب برای برنامه شما بستگی به نیازهای خاص برنامه و منابع موجود داره.پروژه هایی با PWA ساخته میشن تجربه‌ای نزدیک به برنامه‌های Native برای کاربران ارائه میدن، با ویژگی‌هایی مانند push notification و پشتیبانی از حالت Offline، و اغلب برای بهینه‌سازی موتورهای جستجو (SEO) بهتر هستن چون توسط موتورهای جستجو مثل وب‌سایت‌های معمولی index میشن🤩. با این حال، ممکنه با اینکه گفتم هزینه ش از برنامه های Native کمتره ولی در برخی مواقع پیش میاد نیازمنده توسعه بیشتر منابع و تخصص بشیم و به دلیل داشتن یک server، نگهداری و به‌روزرسانی اون هم گرون تر از برنامه های Native برامون آب بخوره.🥺از سوی دیگه پروژه هایی که با SPA ایجاد میشن، تجربه‌ای سریع و پیوسته‌تر برای کاربران ارائه میدن چون به روزرسانی محتوا نیازی به بارگذاری مجدد صفحه کامل نداره. و اغلب آسون‌تر برای توسعه هستن🤩 ، اما ممکن است در به‌روزرسانی کندتر باشن و برای موتورهای جستجو برای پوشش و indexشدن، دشوارتر .🥺این تصویر پایینی استفاده Framework های متفاوت برای ساخت Web Application و PWA هست به گزارش visionvixمَخلص کلامخب دوستان همونطوری که گفتم با توجه به نیاز پروژه مون و شرایط باید سنجید که کدوم تکنولوژی گزینه بهتری برامون بشمار میره و استفاده درست از هر کدوم از این عزیزان 😁 برامون میتونه پیشرفت های فوق العاده ارزنده ای رو به ارمغان بیاره و تجربه کاربری دلنشینی به کاربران محترممون بده. ازتون بی نهایت سپاسگزارم تا انتهای این مقاله همراهم بودید 💐 دل هاتون پر از عشق و آرامش. 🙌 </description><category>محسن محمدی رهنما</category><author>محسن محمدی رهنما</author><pubDate>Thu, 29 Feb 2024 23:44:13 +0330</pubDate></item><item><title>بینندگان عزیز، هم اکنون React 19 !</title><link>https://virgool.ir/@mohammadi.dev91/بینندگان-عزیز-هم-اکنون-react-19-e4xf1vdslhbc</link><description>سلام و عرض ادب خدمت دوستان محترم امیدوارم حال دل همتون خوب باشه 🤗، بالاخره تیم توسعه React نسخه 19 این Framework محشر دارن اراِئه میدن 🤩 ، اما بیاین باهم بررسی کنیم که چه مواردی به این Framework اضافه شده ، پس با من همراه باشین...🥳کامپایلر React: بهینه‌سازی هستهاولین یا به عبارت دیگه مهمترین موضوعی که هست، کامپایلر React هست که دستخوش تغییراتی خفن شده 🤩 به گفته تیم توسعه React js ، &#34;دیگه React Compiler یک پروژه تحقیقاتی نیست: و از قدرت این کامپایلر در حال حاضر در وب‌سایت instagram.com استفاده میشه و ما در حال کار بر روی استفاده این کامپایلر به سایر سطوح در Meta و آماده‌سازی اولین نسخه منبع باز هستیم.&#34; و نکته دیگه که هست کامپایلر React به مسئله Rerender اضافی در برنامه‌های React پرداخته و یک مسئله و چالش رایج برای توسعه‌دهنده ها رو حل می‌کنه. همونطوری که می دونید ما یرای تکنیک‌های Moization از هوک های مثل useMemo و useCallback استفاده میکردیم، اما ممکن بود در صورت استفاده غلط، Performance پروژه های مارو با مشکل مواجه کنن.همونطور که در تصویر مشاهده میکنید، پستی که آقای Clark ( یکی از توسعه دهنده های اصلی React js ) توی شبکه X قرار دادن به این هم اشاه داره که یکی از مواردی تا پیان سال جاری میلادی حذف خواهد شد و دیگه داخل خوده کامپایلر React قرار میگیره دوستانی همچون memo , useMemo, useCallback هستن.😁کامپایلر React دیگه رویکردی متفاوتی رو میخواد عملی کنه، به طور خودکار کد رو بهینه‌سازی می‌کنه بدون اینکه به core mental model ( چارچوب و الگوی اصلی ) مربوط به React  خللی وارد بشه 💥. این می‌تواند بهبود چشمگیری در عملکرد رندرینگ ایجاد کند و منجر به تجربه کاربری فوق العاده تری شود، به ویژه در component های پیچیده که به طور مکرر Rerender می‌شوند.اقدامات ( Actions ) : Streamlining Data Flow and Optimistic Updates پردازش ارسال فرم‌ها و دیگر تعاملات داده‌ای بین client و server ممکن هست که یه کار پیچیده‌ای باشه. حالا Action ها به عنوان یک API جدید که در React 19 معرفی شدند،که این فرآیند را ساده‌تر می‌کند و با ارائه روشی یکپارچه و شناختی (intuitive) حالا منظور از شناختی چیه 🤔 (یعنی که رفتار و عملکرد اون پیش‌بینی‌پذیر و سازگار هست و کاربران به راحتی می‌تونن از اون استفاده کنن بدون نیاز به دانش فنی عمیق).بزارید براتون یه مثال بزنم: &lt;form action={search}&gt; &#xA;     &lt;input name=&#34;query&#34; /&gt; &#xA;      &lt;button type=&#34;submit&#34;&gt;Search&lt;/button&gt;&#xA; &lt;/form&gt;درواقع `action` تعریف شده در function معرف این هست که چگونه داده‌ها ارسال و پردازش میشن. React مدیریت کل lifeCycle رو انجام می‌ده، از جمله عملیات Async و به‌روزرسانی‌های optimistic UI .و اینکه Hook هایی مثل useFormStatus و useFormState دسترسی به state فعلی و  Response form action را فراهم می‌کنند، Data flow و Validation را ساده‌تر می‌کنند.🤩کامپوننت های سمت سرور : آزاد کردن قدرت Server-Side Rendering 💥مشکلات بارگذاری اولیه کُند و مشکلات بهینه‌سازی برای موتورهای جستجو به لطف Server Component ها قابل حل هستن، که یک دیگه از برگه برنده هایه React است. تصور کنین یک صفحه اصلی خبری با مقالاتی که به طور مکرر به‌روزرسانی می‌شن. Render کردن این Component  ها مستقیماً روی Server با استفاده از Server Component، اولین تاثیرات فوق‌العاده سریع را ارائه می‌ده و رتبه‌بندی موتورهای جستجو را افزایش میده 🤩. این برای برنامه‌های با محتوای سنگین یا توسعه دهنده هایی که نیاز به عملکرد SEO بالا دارن، عااااالیه.🥳بارگذاری Asset ها (Asset Loading)  : حفظ رابط کاربری بصورت Sync( دوستان من یه نکته ای رو بگم اینکه برگردوندن یکسری اصطلاحات به فارسی دووشواره 😁 اگه دیدید یه جاهایی مجبور شدم به همون انگلیسی بنویسم بدونین میخواستم همون اصطلاحی که ما توی برنامه نویسی بکار میبریم و رایج هست ، استفاده کنم )خب بریم سراغ ادامه بحثمون ، آیا تا به حال با تغییرات UI در حالت انتظار مثل ( skeleton)  برای بارگذاری فایل‌های استایل یا فونت؟ یه چیزی الان میگم دچار ریزش برگ های خزان میشین 😀خب Asset Loading میاد Suspense را با Resource loading هامون  یکپارچه می‌کنه و تجربه کاربری شیک و مجلسی در اختیارمون میزاره😁. تصور کنید یک صفحه محصول با تصاویر با وضوح بالا. Asset Loading اطمینان میده که تصویر قبل از نمایش آماده است ،و از ایجاد وقفه‌های ناگهانی جلوگیری می‌کنه و یک رابط کاربری زیبا ایجاد می‌کنه.🥳هوک ها ( Hooks):نه تعجب نکنین توی React 19 خبری از Hook جدیدی نیست،🥺 اما نگران نباشین یکسری از Hook های اصلی تغییر اساسی میکنن 🤩هوک های  useMemo و useCallback: قابلیت‌های بهبود یافته برای Memoization دقیق‌تر، که ممکنه تعداد بیشتری از Renderهای غیرضروری را کاهش بده. تصور کنید یک Component list بزرگ که تنها موارد خاصی باید بر اساس تعامل کاربر مجدداً Render بشن.هوک useEffect: کنترل بیشتری بر روی زمان اجرای effect ها، که اجازه میده مدیریت Side effect ها تمیزتر و کارآمدتری داشته باشیم. تصور کنید یک effect که داده‌ها را تنها زمانی که یک کامپوننت خاص mount می‌شه، دریافت می‌کنه.هوک useImperativeHandle: استفاده بهینه‌تر برای ایجاد object های شبیه به ref در functional component ها. تصور کنید یک Carousel Component سفارشی که متدهایی را برای کنترل رفتار اون ارائه میده.کلام آخر:دوستان عزیزم React 19 یک ارتقاء نیست، بلکه دروازه‌ای به تجربه توسعه‌ی Performance پویا و جذابه. از کامپایلر نوآورانه React تا یکپارچگی با اجزای وب، هر ویژگی به شما این امکان رو می‌ده تا رابط‌های کاربری‌ رو ایجاد کنید که فوق العاده باشه. و در آخر از تمامی شما دویتان ممنونم که وقت گذاشتین رو مقاله من رو خوندید و امیدوارم لذت برده باشین. 💐🤗منابعسایت mblogingسایت react.dev</description><category>محسن محمدی رهنما</category><author>محسن محمدی رهنما</author><pubDate>Fri, 23 Feb 2024 15:08:18 +0330</pubDate></item><item><title>احراز هویت (Authentication) با استفاده از NextAuth.js</title><link>https://virgool.ir/@mohammadi.dev91/احراز-هویت-gitlab-با-استفاده-از-nextauthjs-wng3r9vsvm34</link><description>سلام دوستان من دوباره اومدم با یک مقاله جدید ?? همونطور که از عنوان مقاله مشخصه توی این مقاله میخوام عملیات احراز هویت ( یا به زبان غربی Authenticate) از طریق GitLab با استفاده از NextAuth.js رو براتون توضیح بدم. توی این مقاله قصد دارم اول یه توضیح مختصری درباره اینکه NextAuth.js اصلا چی هست و چه کاربردی داره رو براتون توضیح بدم و بعد باهم کاربرد اون رو در غالب یه مینی پروژه با استفاده از Nextjs13 و Typescript باهم انجام بدیم . پس بزن بریم ?درباره NextAuth.jsقبل از اینکه NextAuth.js تعریف کنم اجازه بدید اول Auth.js تعریف کنم که یک به عنوان یک راه حل جامع و کامل احراز هویت بصورت open source برای Web application بکار برده میشه و NextAuth.js رو برای پروژه های Nextjs شما عرضه کرده. حالا این داداشمون (یعنی Auth.js) اومده برای سه تا فریمورک غول، این نعمت بزرگش رو ارائه داده?:فریمورک Next.js: یک فریمورک انعطاف پذیر React که به شما امکاناتی برای ایجاد Web application های سریع رو می ده.ابزاری که کامل باشه برای هر توسعه دهنده React که برای یادگیری و بهبود پروژه های خودش استفاده کنه ، بدون شک Next.js است. ( که من میخوام از این یکی سلطان استفاده کنم ?).فریمورک SolidStart: همونطور که میدونید Web application ها اغلب شامل اجزای بسیاری هستن از جمله Data baseها، سرورها، front-end ،  bundler ، fetching/mutations ، Chaching و زیرساخت و...  حالا این فریمورک میگه &#34; دوستان خوبم به گوش باشید، من بسیاری از این موارد رو خودم handle میکنم و در نهایت اون ها رو بصورت یکپارچه با هم ادغام میکنم . بدون درد و خونریزی ?&#34; و این هم بگم که این فریمورک بر پایه Solidjs و Solid Router هستشفریمورک SvelteKit: ایشون هم در واقع یکی دیگه از فریم ورک هایی هست که برای توسعه Web application بکار برده میشه این نکته رو در نظر داشته باشید وقتی از Svelte استفاده میکنید ، فریمورک اون باید SvelteKit باشه ، یه جور مثل این می مونه که وقتی دارید با React کار میکنید در کنارش از Nextjs استفاده میکنید یا وقتی دارید از vue استفاده کنید در کنارش از Nuxt استفاده میکنید. شروع مینی پروژهخب دوستان خوبم از هر چه بگذریم سخن مینی پروژه خوش تر است ? خب برای شروع دوستان توی مسیر مورد نظرتون که میخواید پروژه Next تون رو نصب و اجرا کنید ، بروید و دستور زیر رو توی ترمینال IDE خودتون ( که من از VScode استفاده میکنم. ) وارد کنید npx create-next-app@latestقبل از شروع نصب سوال هایی میپرسه، من ساختار پروژه رو براساس app گفتم ایجاد کنه نه src . و اینکه از Typescript هم استفاده میکنم ( نگران نباشید سلیقه ای هست و به موضوع بحثمون وابستگی نداره رفقا?).پکیج بعدی که باید نصب کنید دوستان، NextAuth.js هست. npm install next-auth ☢️توجه..توجه . دوستان من زیاد روی UI تمرکز نکردم و گذاشتم به سلیقه خودتون چون خواستم تمرکز رو بزارم برای هدف اصلی بحثمون. پس در هنگام بروز هر حادثه آرامشتون رو حفظ کنید و ماسک های اکسیژن از سقف براتون آویزون میشه و میتونین استفاده کنید?.خب دوستان خوبم وارد سایت NextAuth.js بشین و از پنل سمت چپ گزینه Providers کلیک کنید، از منوی منوی کشویی که باز میشه میتونید متوجه بشید به شما لیستی از گزینه هایی رو در اختیارتون میزاره که از طریق اون ها میتونید عملیات Authentication رو انجام بدید. خب ما میخوایم با استفاده از GitLab این عملیات رو انجام بدیم پس از داخل منوی باز شده، گزینه GitLab رو انتخاب کنید. در بخش Configuration روی لینک پایین اون کلیک کنید ( https://gitlab.com/-/profile/applications ) فقط دوستان حواستون باشه حتما باید حساب کاربری توی GitLab داشته باشید.حالا بعد از اینکه وارد صفحه مورد نظر شدین روی دکمه Add new application ( که در تصویر مشخص کردم) کلیک کنیدخب توی صفحه ای براتون باز شد در قسمت Add new application ازتون یه Name میخواد و یه Redirect URI . توی قسمت Name اسم دلخواه تون رو بنویسید ولی توی قسمت Redirect URI این لینک رو بنویسیدhttp://localhost:3000/api/auth/callback/gitlab ?یه نکته ای هم که باید بهش دقت کنید دوستان حواستون باشه که localhost تون روی هر پورتی که هست توی لینکی که هم براتون فرستادم همون رو بزارید. حالا بریم سراغ موارد بعدی، تیک گزینه Confidential بزارید فعال باشه و در آخر در بخش Scopes ، گزینه های api و Read_user و Profile و email رو فعال کنید. خب وارد صفحه ای که میشید بهتون یه Application ID و یه Secret میده حواستون باشه این دوتا رو یه جا ذخیره کنید باهاشون کار داریم. صفحه رو تایید کنید.خب بریم سراغ پروژه ای که با Next13 ایجاد کردیم، در وهله اول دوستان خوبم یه فایل env. ایجاد میکنیم و داخلش این سه تا متغییر رو مینویسمNEXTAUTH_SECRET= ( رمز دلخواه )AUTH_GITLAB_ID= ( Application ID )AUTH_GITLAB_SECRET=( Secret )خاطرتون هست بهتون گفتم Application ID و Secret رو یه جا ذخیره کنید باهاش کارداریم؟! دقیقا همینجاست. براتون در قسمت بالا مشخص کردم که جلو کدوم متغییر، کدوم قسمت رو جایگذاری کنید. و اما NEXTAUTH_SECRET یه رمز دخواه قرار میدید و این رمز باعث هش کردن توکن ها و کوکی هامون میشه من بهتون پیشنهاد میدم برای تولید رمز از کد زیر توی ترمینال تون استفاده کنید openssl rand -base64 32یا از طریق لینک مربوط به خوده Vercel استفاده کنید. مقداری که بهتون داد رو بریزید داخل متغییر NEXTAUTH_SECRET . حالا مرحله بعدی که باید انجام بدید اینه که توی پوشه app (دوستان لازمه عرض کنم من پروژه  Nextjs م رو براساس app ایجاد کردم) به صورت زیر پوشه بندی ایجاد کنیدapi/auth/[...nextauth]/route.tsداخل فایل route.ts به این صورت مینویسیمشاید براتون سوال بشه چرا جلوی مقادیر ClientId و clientSecret علامت تعجب (!) گذاشتم ، اگر این علامت رو نزاریم Typescript بهمون به نوعی خطا میده که میگه &#34; داداش این مقادیری که به این دوتا کلید پاس دادی ممکنه undefined باشه هااا! و این که این دوتا کلید اصلا مقدار undefined رو هیچ جوره قبول ندارنااا! ? &#34; خب ما هم اینجا بهش میگیم اصلا جای دووشواری نیست ? یه علامت تعجب میزاریم آخر مقادیر مربوط به کلید هامون، اینطوری بهش میگیم که خیالت راحت این متغییر هایی که ما پاس دادیم به این کلید ها، مقدار دارندر وهله بعد یه پوشه دیگه توی auth ایجاد میکنیم به نام token داخل فایل route.ts این کد رو مینویسیماین کد رو نوشتیم تا زمانی که عملیات احراز هویت با موفقیت انجام شد توکن مورد نظر رو دریافت کنیم تا به وسیله اون اطلاعات مورد نظرمون ( نام کاربری و ایمیل و...) دریافت کنیم.خب دوستان ما تا اینجای کار تمام پیاده سازی های احراز هویت سمت Server رو انجام دادیم حالا میخوایم وقتی همه چی گل و بلبل پیش رفت کاربر هم اون رو ببینه ( به قول یکی از همکارامون &#34; sense&#34; کنه ? ) پس بریم برای پیاده سازی سمت Client.بزارید قبل پیاده سازی فقط قبلش توضیح بدم میخوام چیکار کنم بعد بریم سراغ کد نویسیش ، ببینید دوستان من برای اینکه به کاربر اعلام کنم عملیات احراز هویت ش با موفقیت پیش رفته ، بعد از اینکه توکن رو دریافت کردم و توکن اون مشکلی نداشت ، اطلاعاتی مثل نام و نام خانوادگی ش ( همون نامی که توی حساب کاربری GitLabش ثبت نام کرده) بهش نشون بدم . این قضیه رو یه Custom Hooks که در NextAuth هست به نام useSession برامون فراهم کرده با استفاده از این hook به اطلاعات کاربر ( نام ، ایمیل، آواتار و...) و حتی وضعیت احراز هویت اون (status) میتونیم دسترسی داشته باشیم.فقط قبلش ما یه Provider تعریف کنیم تا بتونییم به اون اطلاعات کاربر هرجای پروژه که خواستیم دسترسی داشته باشیم. خب بریم سراغ پیاده سازیش ، در قدم اول داخل پوشه app همچین چیزی رو پیاده کنیدداخل AuthProvider.tsx در واقع provider رو که صحبتش رو کردیم رو پیاده سازی میکنیم، به این شکلحالا یه component هم درست میکنیم که عملیات signIn و signOut مون رو انجام بده که من طبق ساختاری که در بالا گفتم اسمش رو Signin.tsx قرار دادم و داخلش به این شکل نوشتمدوستان خوبم همونطوری که مشاهده میکنید NextAuth از طریق useSession  وضعیتهای (status) مربوط به احراز هویت کاربر ( loading , authenticated , unauthenticated) در اختیارمون قرار میده، منم با توجه به هر وضعیت گفتم که عمل خاصی رو نمایش بده به عنوان مثال توی حالت loading گفتم که یک spinner بهم نشون بده ( با استفاده از کلاس های TailwindCss) و توی حالت authenticated بهم نام کاربر رو نشون بده ( همونی نامی که توی حساب کاربری GitLab ش ثبت نام کرده ) به اضافه اینکه یه دکمه کنارش که عملیات signOut رو انجام میده ، جالبه بدونید برای SignOut کردن هم کافیه فقط توی event مربوط به element تون تابع signOut فراخوانی کنید خوده NextAuth به همین راحتی handle کرده این قضیه رو ? همینطور برای برای signIn، فوق العادس نه ! ? . و در آخر هم برای زمانی که unauthenticated بود دکمه signIn به همراه action مربوطه ش ( چند خط قبل توضیح دادم) رو نمایش بده . به همین راحتی ?حالا وقته اینه که این component رو به همراه provider ی که ایجادش کردیم ، استفاده کنیممن یه فایل layout.tsx داخل app ایجاد کردم و داخلش به این شکل نوشتمخب همونطوری که میبینید دوستان من اومدم یه navbar ایجاد کردم و چون این navbar داخل فایل layout م هست پس یعنی توی کل پروژه قابل مشاهده هست و از طرفی اون provider ی که ایجاد کرده بودیم هم (AuthProvider) همینجا ازش استفاده میکنیم و توی کل پروژه هم به اطلاعات کاربر احراز هویت شده دسترسی داریم.  navbar رو هم داخل اون قرارش میدیم و در آخر هم component مربوط به signIn رو داخل یه li قرار دادم و تمام به همین راحتی به همین خوشمزگی?مَخلص کلامجمله پایانی که باید بگم که دوستان مبحث Authentication یا همون احراز هویت یکی از اساسی ترین مباحث سمت امنیت وب سایت تون هست و اگر دغدغه پیاده سازی امنیت سمت پروژه های Nextjs رو دارید یه سیستم احراز هویت با پیاده سازی راحت ( به این معنی بیشتر از 75 ارائه دهنده سرویس که یکیش همینی بود که توی این مقاله پیاده سازی ش کردیم &#34;GitLab&#34; بدون پیچیدگی های بی مورد توی پیاده سازی) منعطف بودن ( به این معنی که توی فریم ورک های خفن مثل Next.js, SolidStart, SvelteKit خیلی شیک با دیتابیس های MySQL, Postgres, MSSQL, MongoDB و... کار میکنه ) ودر آخر امنیت بالا (به این معنی که امنیتش بر اساس CSRF  هست و JWT به همراه JWS / JWE / JWK و همچینین  همه چی سمت sever پیاده سازی میشه و هیچ چیزی سمت client نیست) NextAuth.js میتونه گزینه مناسبی براتون باشه . خیـــــــــلی ممنون از همتون که تا پایان این مقاله همراه من بودید امیدوارم دوستان براتون مفید باشه . مشتاقانه منتظر سوالات ،نکته ها، انتقادات و پیشنهاداتون هستم رفقا?. مراقب خودتون باشید. روز و روزگارتون خوش??</description><category>محسن محمدی رهنما</category><author>محسن محمدی رهنما</author><pubDate>Tue, 17 Oct 2023 12:52:16 +0330</pubDate></item><item><title>استفاده async/await در حلقه map جاوااسکریپت</title><link>https://virgool.ir/@mohammadi.dev91/استفاده-asyncawait-در-حلقه-map-جاوااسکریپت-gmbx24j2wbdl</link><description>سلام دوستان خوبم وقتتون بخیر 🤗 . شاید بعضی وقتا براتون این اتفاق افتاده باشه که Dataیی رو دارید از یه Api میگیرید و برای اینکه روی اون Data تغییراتی انجام بدید باید روی اون map بزنید و توی این mapی که دارید میزنید هر loop که بخواد اجرا بشه باید loop قبلیش تکمیل شده باشه . در حالت معمول که بخواین از map استفاده کنین به یکسری مشکل میخورید 😕 ولی اگه به حرف من گوش کنین به مشکل نمیخورین 🥳 پس با من همراه باشین.async/await در حلقه mapشبیه سازی Apiدر مرحله اول من اینجا یه تابع دارم که در واقع اومده همون Api مورد نظرمون رو که میخوایم روش map بزنیم رو شبیه سازی کرده که همانطور که در پایین می بینید ما یک آرایه از نام های کاربری و یک تابع داریم که یک پارامتر را می گیره و یک رشته را برمی گردونه.const usernames: string[] = [&#34;jordanrjdev&#34;, &#34;anonymous123&#34;, &#34;channelyy&#34;]; &#xA;const simulateFetchData = (username: string): Promise&lt;string&gt; =&gt; {&#xA; return new Promise((resolve) =&gt; { setTimeout(() =&gt; { resolve(`${username} is a valid username`); }, 1000); });&#xA; }حالا میخوایم آرایه نام کاربری را تکرار کنیم تا داده های شبیه سازی شده هر کاربر رو با map بدست بیاریم.const dataUsers = usernames.map(async (username) =&gt; {&#xA; return await simulateFetchData(username);&#xA; });&#xA; console.log(dataUsers);حالا بریم با هم log مون رو ببینیم تا ببینیم خروجی چیه ![ Promise { &lt;pending&gt; }, Promise { &lt;pending&gt; }, Promise { &lt;pending&gt; } ] بله همونطور که مشاهده میکنید خروجی چیزی جز Promise های pending نیست که داره بهمون نشون میدهاین هم بخاطر ماهیت async/await هست که از Promise استفاده میکنه و اینطور هست که توی هر گام از حلقه map مون صبر نمیکنه تا نتیجه Promise برگرده به همین خاطر همه گام های map مون در حالت معلق ( pending ) باقی می مونن.حالا چاره چیه؟?استفاده از For ofراه حل اول استفاده از حلقه for..of هست بریم با هم ببینیم چجوری پیاده سازی میشهconst getWithForOf = async() =&gt; {&#xA;   console.time(&#34;for of&#34;);&#xA;   const data = [];&#xA;   for (const username of usernames) {&#xA;     let dataUser = await simulateFetchData(username);&#xA;     data.push(dataUser);&#xA;   }&#xA;   console.timeEnd(&#34;for of&#34;);&#xA;}&#xA;getWithForOf();این راه حل خوبیه و رایج هست ولی مشکلی که داره زمان زیادی رو صرف میکنه تا اون چیزی رو که میخوایم رو بهمون بده ? توی کد دقت کنین از console.time استفاده کردم تا ببینید زمانی که صرف میشه چقد هست که خروجی که بهمون نشون میده به نظرم فاجعه س ? چون حالا این یه تابع ساده بیشتر نیست که انقد زمان صرفش کرده، واسه Data ی واقعی میخواد چیکار کنه ! ?for of: 3.012sاستفاده از Promise.allراه حل دیگه ای که خودمم اون رو پیشنهاد میدم (حالا بازم بستگی به شرایط داره) استفاده از Promise.all هست، دوستان.const getWithPromiseAll = async() =&gt; { &#xA;console.time(&#34;promise all&#34;); &#xA;&#xA;let data = await Promise.all(usernames.map(async (username) =&gt; { &#xA;return await simulateFetchData(username);&#xA; })) &#xA;&#xA;console.timeEnd(&#34;promise all&#34;); }&#xA; getWithPromiseAll();خاطرتون هست که بهتون گفتم  async/await از Promise استفاده میکنه ! یعنی این کدی که داشتیم usernames.map(async (username) =&gt; {&#xA;return await simulateFetchData(username);&#xA;})هر گام map مون، بهمون یه Promise برمیگردوند، درسته! حالا ما توی روش دوم اومدیم از Promise.all استفاده کردیم که بیاد تمامی Promise هامون رو نتیجه ش رو بهمون برگردونه ( فقط این نکته حواستون باشه Promise.all ببینه  یکی از Promise ها reject شده باشه کل عملیاتش رو reject میکنه ، از بس که بی اعصابه این متد 😁) کلا این متد فوق العادس برای زمانی که کدهای Asynchronous دارید و میخواید بصورت موازی همه چی پیش بره.حالا بریم ببینیم خروجی console.time مون چیهpromise all: 980.3000000119209msیعنی این دوستمون کار رو نذاشت به یک ثانیه هم برسه 🤩 نتیجه گیریهمونطور که من همیشه میگم و الانم میگم بهتون، با قطعیت نمیگم که کدوم روش بهتره ، اگه شرایط Performance رو در نظر بگیریم خب طبیعتاً Promise.all عالیه  ولی یه مواقعی ممکنه بخواید از حلقه for استفاده کنید پس اون موقع چاره ای جز این نداریم که از for..of استفاده کنیم . خب دیگه امیدوارم دوستان این مقاله براتون مفید بوده باشه و جا داره اینجا از دوست و همکار خوبم محمدرضا تشکر کنم که باعث شد این مقاله رو بنویسم و  همینطور دوستمون Jordan Jaramillo . شب و روز تون خوش مراقب خودتون باشید 💐.</description><category>محسن محمدی رهنما</category><author>محسن محمدی رهنما</author><pubDate>Fri, 07 Apr 2023 22:06:43 +0330</pubDate></item><item><title>کار با React Query در Nextjs</title><link>https://virgool.ir/@mohammadi.dev91/کار-با-react-query-در-nextjs-vg00ea5azb3f</link><description>سلام دوستان خوبم !?، توی این مقاله میخوام یه توضیح درباره این که React Query چی هست و کجا برامون کاربرد داره و اینکه پیاده سازی اون توی Nextjs  چجوریه رو با استفاده از یه مینی پروژه توضیح بدم، خوشحال میشم تا آخر این مقاله همراه من باشین.Next.js vs ReactQueryدرباره React Queryخب بیایین اول درباره اینکه React Query چی هست و چکاری برامون انجام میده صحبت کنیم ?. React Query یک کتابخانه مدیریت داده Preconfigured ( از پیش پیکربندی شده ) ReactJS است، که به شما قدرت و کنترل بر مدیریت server-side (حالت سمت سرور)،  Fetching و ذخیره داده ها و مدیریت خطاها را به روشی ساده و کاملا راحت بدون اینکه تأثیری سوء ی بر Global state برنامه شما بزاره.خب ما تا اینجا فهمیدیم تعریف React Query چیه ، حالا بریم ببینیم کارش چیه . همونطور که خودتون بهتر میدونید داده های سرور Async هستند و نمیشه داده ها رو در React ذخیره کرد. حالا چاره چیه ? آهااا اینجا جایی که کتابخانه React Query می درخشد ? تا به ما این امکان رو بده تا داده های Async را دستکاری کنین، اونارو را در حافظه پنهان یا همون Cache نگه داری کنیم و همچنین داده های قدیمی را به روز و یا اون ها رو Synchronize کنیم من که خودم تا باهاش کار نکرده بودم باورم نمیشد همچین چیز خفنی باشه. ?ویژگی های React Queryخب من اینجا چندتا از ویژگی های این کتابخونه جادویی رو براتون آوردم بریم باهم بررسیش کنیم.ذخیره سازی(Caching): Window Focus Re-fetching – این امکان را به شما میده تا بسته به فعالیت برنامه شما، داده ها را از قبل واکشی (Fetch) کنه.درخواست مجدد(Request retry): امکان تنظیم تعداد دفعات مجدد درخواست در صورت بروز خطا.واکشی اولیه (Prefetching) - بسته به اینکه برنامه شما پس از درخواست شبکه به‌روزرسانی به داده‌های تازه نیاز دارد، می‌تواند داده‌ها را از قبل واکشی کنه. این می تونه داده ها را در پس زمینه به روز کنه.راستی داشت یادم میرفت ?ویژگی دیگه ای هم که داره اینه که می‌تونید از Cache های پیچیده استفاده کنید تا بتونید برنامه کاملاً بهینه داشته باشین.از هر چه بگذریم سخن کد خوش تر است ?خب بیاید این دوستمون رو توی عمل تستش کنیم ببینیم چند مرده حلاجه ، میخوام یه مینی پروژه رو باهم ببریم جلو با استفاده از nextjs  . خب قبل از هر کاری وارد سایت Nextjs میشیم و کد دستوری زیر رو داخل ترمینال VScode (حالا با توجه به IDE که استفاده میکنین من اینجا از VScode استفاده کردم?) وارد میکنید npx create-next-app@latest --typescriptبعد از اتمام نصب CNA ،  میریم سراغ نصب axios برای انجام عملیات CRUD روی Api مون . npm i axios  بعد از اون حالا پکیج React Query رو نصب میکنیم با این خط دستوری که براتون در پایین نوشتمnpm i @tanstack/react-query یکی دیگه از ابزار های قدرتمند React Query که میخوام بهتون معرفی کنم DevTools اون هست.npm i @tanstack/react-query-devtools کاری که این ابزار برامون میکنه ، نمایش تمامی اکشن هایی رو که ما روی query هامون میزنیم و اتفاقاتی روی اون ها می افته و نمایش خطاها درصورت وجود مشکل در خصوص تغییرات روی query ها و ... در کل بگم از شیر مرغ تا جون آدمی زاد رو توی فرآیندهایی که روی query هامون میزنیم رو بهمون نشون میده این بزرگوار ? که هم در زمانمون صرفه جویی بشه و هم کد بهینه تری بنویسیم، اگه بخوام مثال بزنم یه جور مثه Redux DevTools می مونه ، حالا توی پروژه کامل بهتون توضیح میدم چجوری کار میکنه نگران نباشین. خب الان پروژه مون به Nextjs  و React Query مسلح شد ، حالا بریم سراغ این که با اینا میخوایم چیکار کنیم.  توی این پروژه ای ما میخوایم با کمک هم بنویسیمش میخوایم لیستی از Post ها رو بگیریم روی اون Pagination انجام بدیم و روی هر کدوم از Post ها که کلیک کردیم Comment مربوط به اون پست نمایش بدیم. خب در وهله اول توی پروژه ای که ایجاد کردیم وارد pages/_app.tsx میشیم و تگ Component رو داخل provider مربوط به React Query میزاریم به این شکل که در تصویر پایین مشاهده میکنید خب تبریک میگم الان پروژه تون یه پروژه Nextjs ی شد که با React Query تونستید اون رو sync کنین ? خب بریم ببینیم چیکار کردیم، اصلا نگران نباشین هیچ کار عجیب غریبی نکردیم ، ببینید در وهله اول اومدیم QueryClientProvider ( همون provider ی که در قسمت بالا عرض کردم) رو از React Query مون import کردیم و تگ Component رو داخل اون قرار دادیم تا هر جای پروژه مون به query ها مون دسترسی داشته باشیم بعد از اون اومدیم  Hydrate اضافه کردیم تا وقتی خواستیم اکشنی روی query ها مون بزنیم ( ویرایش و حذف و... ) nextjs نیاد خطای اینو بده که &#34; آقا دیتای سمت سرور فرق میکنه با کلاینت چرا؟!!?&#34;  حالا من توی این مقاله  درباره Hydration توضیح دادم چیه اگه خواستین بیشتر بدونین بخونیدش بد نیست. حالا بعدش ReactQueryDevtools  رو اضافه کردیم بخاطر اون مواردی که در بالا در خصوص DevTool خدمتتون عرض کردم و در آخر تمام ، نه نه نه صبر کنید ! کلا تموم نشد ، این بخش فقط تموم شد ?. فقط تا الان ما پروژه Nextjs رو آماده کردیم که از React Query بتونیم استفاده کنیم.خب توی این مرحله ما میخوایم یه لیست ده تایی از پست ها رو دریافت کنیم ( با استفاده از React Query ) ، در وهله اول یه صفحه در پوشه pages با عنوان posts ایجاد میکنیم و بعد از اون یه تابع async برای get کردن پست هامون ایجاد میکنیم به این شکل pages/postsهمونطر که مشاهده میکنیم من برای دریافت Fake Api از  jsonplaceholder استفاده میکنم حالا شما از هر کدوم از Fake Api که دوست داشتین استفاده کنین . خب الان میخوایم دیتای این تابع مون رو با استفاده از ReactQuery استفاده کنیم . برای این کار باید از useQuery استفاده کنیم که یه custom hook برای React Query هست که کارش اینه که برامون عملیات Data fetching رو انجام میده، useQuery  دو تا کلید میگیره اولی از نوع آرایه ای هست که نام query که میخوایم روی اون عملیات انجام بشه (Query key) و دومی تابع میگیره (Query function)، که در واقع تابعی هست که میخوایم براساس query ، برامون دیتای مورد نظر رو برگردونه . حالا امیدوارم حدس زده باشید که توی useQuery که میخوام بنویسم پارمتر اول و دوم چی هست . آفرین درست حدس زدین (هرچند که نمیدونم چی حدس زدین  ?) پارامتر اولمون میشه &#34;posts&#34; و پارامتر دومون هم میشه تابع fetchPosts const {data} = useQuery([&#34;posts&#34;],fetchPosts);  خب ما تونستیم با useQuery دیتا مون رو دریافت کنیم ، حالا بریم ازشون استفاده کنیم . همونطور که در کد بالا مشاهده میکنید useQuery بهمون کلید data رو برمیگردونه و ما میتونیم با استفاده از این کلید به دیتای مورد نظرمون دسترسی داشته باشیم و کافیه توی return صفحه مون (همون جا که JSX هارو مینویسیم) به این شکل عمل کنیمuse data from useQueryاین هم یه نمای کلی از کدی که نوشتیم خب دوستان تبریک میگم شما تونستین عملیات get از api مورد نظرتون با استفاده از ReactQuery پیاده سازی کنین ? باور نمیکنین !!! دوشواری نداره که ? الان با مدرک بهتون ثابت میکنم . در وهله اول پروژه تون رو run کنید بعد از اینکه پروژه run شد ، پایین صفحه سمت چپ لوگوی ReactQuery رو مشاهده میکنید ( شبیه یه گل قرمز هست) بعد از اینکه روش کلیک کردید با همچین صحنه ای رو به رو میشیدروی posts کلیک کنید چیزی که به شما نشون میده به این شکل هست توی قسمت Data Explorer که مشاهده میکنین ، میبینین که لیست پست هاتون رو آورده و این به این معنی هست که دریافت دیتا از Api با استفاده از ReactQuery موفقیت آمیز بوده دوستان من ?. دوستان ، ما حتی میتونیم مدیریت داشته باشیم برای مواقعی که data تا زمانی که به کاربر نمایش داده میشه ممکنه طول بکشه توی این مدت زمان بهش یک Loading نمایش بدیم یا برای زمانی که Api مون به مشکلی خورد و با خطا مواجه شد چه چیزی به کاربر نمایش بده.همونطور که مشاهده میکنید با استفاده از کلید isLoading میتونیم مشخص کنیم برای زمانی که در حال دریافت data هستیم بهمون چی نشون بده یا اگه با خطا مواجه شدیم برامون چیکار کنه لیست کاملش رو میتونین از اینجا مشاهده کنید . شاید براتون سوال بشه فرق isLoading با isFetching توی چیه؟ ? isLoading vs isFetchingخب ببینید isFetching برای زمانی هست که میخوایم بررسی کنیم آیا api مون Refetch شده یا نه اگه بهمون true برگردوند یعنی Api مون Refetch شده ولی در حالت دیگه یعنی isLoading قضیه یه خورده فرق میکنه یعنی اینکه ما با Fetching کار نداریم موضوع دیگه برمیگرده به فاصله زمانی که اولین درخواست رو ما به Apiمون میدیم تا زمانی که جوابش بیاد ، که اینو رو با isLoading مدیریت میکنیم که اگه true بود یعنی در حال دریافت پاسخ درخواست داده شده هست که ما در کد بالا اومدیم با نمایش عبارت Loading توی یه تگ h3 اون رو مدیریت کردیم .خب بریم سراغ بخش بعدی پروژه مون، میخوایم کاربر روی هر پستی که کلیک کرد کامنت مربوط به اون پست هم نمایش بده ، در قدم اول یک component باید بسازیم که تا دیتای مربوط به کامنت هامون رو توی اون نمایش بدیم (من نام component رو PostDetail گذاشتم ) خب داخل این component مون نیاز داریم که لیست کامنت ها رو براساس پست ها دریافت کنیم پس اول نیاز هست یه تابع بنویسیم که کامنت های مربوط به هر پست رو (براساس آی دی اون پست) بهمون بده یعنی به این شکل که مشاهده میکنید و حالا داخل بدنه ی component میایم query میزنیم تا کامنت هامون رو برا اساس پست ها دریافت کنیم خب بر میگردیم به صفحه مربوط به پست هامون همون جایی که لیست پست هارو نمایش میدادیم چرا برگردیم؟ به این خاطر که میخوایم خاصیت کلیک روی هر پست بزاریم که وقتی کلیک کرد کامنت مربطو به اون یا بهتر بگم کامپوننت PostDetail اجرا بشه . در وهله اول یه useState مینویسم که روی هر پستی که کلیک شد توی state مون ذخیره بشه و اون state پاس بدیم به props کامپوننت PostDetail مون ( که نام propsی بهش داده بودیم post بود) تا براساس اون آی دی پست رو بگیره و کامنت رو تحویل بده  خب برنامه رو run کنید ببینید چه اتفاقی الان افتاده . یه اتفاق عجیب درسته ؟ شما روی هر پستی که کلیک میکنید کامنت های اونا شبیه هم هست بزارید واضح بگم ، روی هر پستی که کلیک میکنید اصلا کامنت ها آپدیت نمیشن !! و صفحه برای بار اول که load میشه فقط کامنت مربوط به اون پستی که روش کلیک کردیم رو نمایش میده و بعد از اون روی هر پست دیگه ای که کلیک میکنیم همون کامنت رو نشون میده  ? اینجاست که باید بگم &#34; توجه .. توجه.. دیگر نگران ریزش مو .. اِاِاِ نه ببخشید اشتباه شد ?&#34; . این مسئله به این خاطر هست که ما به React Query مون نگفتیم که هر کامنت مون وابستگی داره به یَک یَک پست ها مون . یعنی چی ؟ یعنی این که کامنت هایی که داریم براساس post id  هر پست نمایش داده میشن و تفکیک میشن ، حالا تکلیف چیه؟ فقط کافیه توی useQuery که نوشتیم و پارامتر اولی که comments رو بصورت آرایه بهش پاس دادیم ، آیتم دوم آرایه رو post.id بنویسیم.  const {data} = useQuery([&#34;comments&#34;, post.id] , () =&gt; fetchComments(post.id) );اینطوری به React Query مون میفهمونیم که عزیزم این کامنت ها وابسته هستن به پست حالا بر چه اساس؟ براساس آی دی پست ها ( یا همون post.id ). الان دیگه روی هر پستی کلیک کنید کامنت مربوط به اون پست رو مشاهده میکنید. ?خب ما تا به اینجای کار تونستیم اطلاعات مورد نظرمون رو براساس useQuery دریافت و یا درواقع get کنیم حالا برای مابقی فرآیند ها چی؟ یعنی برای ایجاد، حذف و به روز رسانی، برای اون ها هم باید از همین روش استفاده کرد؟ در جواب باید گفت که خیر. اینجا رَوش کمی متفاوت میشه. React Query میگه که شما وقتی دارید Data ی رو تغییر میدید و ماهیت اون تغییر میکنه پس در اصل شما اومدید اون رو Mutate کردید (یا به عبارت دیگه اون دیتا رو جهش دادید). پس باید از یه Custom hook به نام useMutation  استفاده کنید ، Mutation برخلاف query ها، معمولاً برای ایجاد، به روز رسانی، حذف داده ها و یا انجام Server side-effects استفاده می شوند. برای این منظور React Query همونطور که در بالا عرض کردم میاد میگه که بیاد برای اینکار از useMutation استفاده کنید. خب بریم باهم عملیات حذف پست رو با استفاده از useMutation پیاده سازی کنیم.در وهله اول باید یه تابعی بنویسیم که عملیات حذف رو برامون انجام بده توی بدنه تابع اصلی مون (یعنی همون PostDetail) یه const درست میکنیم و تابعی برای حذف نوشته بودیم رو به useMutation پاس میدیم به این شکلconst deleteMutation = useMutation((postId) =&gt; deletePost(postId));حالا در قسمت return میایم یه دکمه حذف درست میکنیم و توی  اون ، deleteMutaion رو پاس میدیم &lt;button ={() =&gt; deleteMutation.mutate(post.id)}&gt;Delete&lt;/button&gt;حالا قسمت باحال ماجرا اینجاست که میتونید مدیریت کنید زمانی داره عملیات حذف انجام میشه چه چیزی نمایش بدید یا زمانی که با موفقیت یا با خطا رو به رو میشه چه فرآیندی انجام بشهبه همین راحتی ! یه useMutation مینویسی اون تابعی که میخوای رو هم بهش پاس میدی خودش بقیه کارارو میکنه به همین خفنی !?حالا بریم برای update پست ها ، اینم مثه همینه فقط توی تعریف تابع باهم فرق میکنن حالا پایین useMutation قبلی که برای حذف نوشته بودیم یه const دیگه تعریف میکنیم به این شکلconst updateMutation = useMutation((postId) =&gt; updatePost(postId));توی قسمت return  یه دکمه ایجاد میکنیم به منظور بروزرسانی و توی  اون نام مغییر بالا که نوشتیم رو بهش پاس میدیم به این شکل &lt;button ={() =&gt; updateMutation.mutate(post.id)}&gt;Update title&lt;/button&gt;و در نهایت به این شکل خب دوستان پروژه مون داره به پایان خودش نزدیک میشه میرسیم به بخش نهایی که خیلی مهم هست که اونم Prefetching  هست بزارید با یه مثال براتون توضیح بدم ، شده براتون اتفاق بیوفته مثلا توی صفحه تو Pagination داشته باشید و روی هر صفحه که کلیک میکنید تا زمانی که دیتا بیاد روی صفحه بشینه قبلش یه Loading یا Skeleton نمایش بدید تا به کاربر بگید در حال دریافت اطلاعات از سمت سرور هستید ! خب این دوستمون یعنی PrefetchQuery کار رو برامون راحت کرده ، همونطور که از اسمش مشخصه دیتا رو یه بار از قبل Fetch میکنه برامون بدون اینکه لازم باشه loading یا هرچیه دیگه قبلش نشون بدیم.الان میخوام یه Pagination توی پروژه مون با اسفاده از همین ابزار پیاده سازی کنم .خب در این بخش اول باید توی تابع دریافت پست هامون یه تغییر ریزی انجام بدیم یه کوئری به نام page به api مون اضافه کنیم و اون رو داینامیک کنیم یعنی بصورت زیرفقط قبلش بیایم یه متغییر کلی بنویسیم که حداکثر تعداد صفحه هایی که میخوایم توی صفحه مون داشته باشیم رو بگیم. const maxPostPage = 10; توی بدنه تابع اصلی مون ( Posts ) یه useState مینویسیم برای موقعیت فعلی صفحه مون و مقدار پیش فرض اون هم عدد یک رو میدیم یعنی همون صفحه اول const [currentPage, setCurrentPage] = useState(1);  حالا اون useQuery که نوشته بودیم رو به شکل زیر تغییر میدیمconst { data,isError,error,isLoading }= useQuery( [&#34;posts&#34;, currentPage ],() =&gt; fetchPosts(currentPage));&#xA;همونطور که مشاهده میکنید چون تابع fetchPosts آرگومان میگیره پس به نوعی به useQuery میگیم که query مون وابستگی داره پس به آیتم دوم آرایه مون اون state مون رو پاس می دیم خب همونطور که در تصویر بالا مشاهده میکنید اول اومدم از یه Custom hooke استفاده کردم به نام useQueryClient تا بتونیم با استفاده از اون عملیات Prefetch صفحه هام رو انجام بدم این QueryClient کلی متد دیگه هم داره که میتونید از این اینجا مشاهده کنید. بعدش اومدیم یه useEffect نوشتیم داخلش شرطی مبنی بر اینکه اگه صفحه جاری مون کوچکتر از تعداد حداکثر کل صفحه هاتمون بود بیاد یه دونه به صفحه جاری اضافه کنه در قالب nextPage و به prefetchQuery پاسش میدیم تا برامون صفحه بعدی رو از قبل Fetch کنه ، همونطور که میبینید تعریف prefetchQuery  فرقی با useQuery هایی که مینوشتیم نداره یعنی این هم یه QueryKey  که [&#34;posts&#34;, nextPage] هست میگیره و یه QueryFunction که fetchPosts(nextPage) هست رو میگیره و در نهایت currentPage, queryClient رو به Dependency array مربوط به useEffect مون میدیم تا هر موقع تغییر کردن عملیات Re-render مون اتفاق بیوفته.خب حالا بریم سراغ UI مون خب دوستان عزیزم این هم از Pagination و پروژه مون هم به پایان رسید . من باز فایل پروژه رو میزارم تا داشته باشین .فایل پروژهنتیجه گیریخب دوستان ما تا الان با تعریف React Query و کاربرد اون آشنا شدیم تونستیم باهاش یه مینی پروژه رو CRUD کنیم. React Query گسترده تر از این حرفاس که بخوایم به عنوان یه ابزار معمولی بهش نگاه کنیم و من سعی کردم تا جای ممکن اون قسمت هایی که ممکنه توی پروژه های خودتون با اون به چالش بخورین رو تو این مینی پروژه پوشش بدم و حتما تاکید میکنم اگه میخواید Chaching سمت سرور داشته باشید این ابزار خیلی میتونه کمکتون کنه، بخصوص در زمان query زدن های تودرتو و اینکه React Query وقتی ببینه شما توی پروژه تون از چند تا api یکسان استفاده کردید ، میاد اون رو Cache میکنه تا الکی request اضافی سمت سرور نفرسته و در نهایت کلی خوبی های دیگه، این هم قبول دارم که هیچ ابزاری کامله کامل نیست باید دید نیاز و وسعت پروژمون در چه مقیاسی هست و به تبعه اون از اون ابزار و پکیج مورد نظر استفاده کرد. امیدوارم مقاله مفیدی باشه براتون، از صمیم قلبم آرامش براتون آررزو میکنم.  </description><category>محسن محمدی رهنما</category><author>محسن محمدی رهنما</author><pubDate>Sun, 02 Apr 2023 14:33:17 +0330</pubDate></item><item><title>کاربرد CSR , SSG,SSR و ISR در Next js</title><link>https://virgool.ir/@mohammadi.dev91/کاربرد-csr-ssgssr-و-isr-در-next-js-z6pbrwaecudr</link><description>سلام به همگی ، یه چند وقتی هست دارم در رابطه با next js مطالعه میکنم تا اینکه رسیدم به مبحث  Page re-rendering در Next js و از اونجایی که پیدا کردن منابع فارسی در این خصوص بیشتر شبیه به یه جوک هست 😁 به همین خاطر تصمیم گرفتم خودم یه مقاله کاملا بومی سازی شده در این باره بنویسم . پس بزن بریم ! بزن بریم به زبان غربیقبل اینکه بریم سراغ معرفی متد ها ، بیاین قبلش بیینیم اصلا next js چجوری عمل Rendering رو انجام میده  یا اصلا Rendering یعنی چی؟! منظور از Rendering در Nextjsدر واقع بخوام خلاصه بگم ، به عمل تبدیل کدهایی که (داخل پروژه React تون ) مینویسید و ارائه اون بصورت رابط کاربری HTML رو Redering  میگن. عملیات Rendering هم میتونه سمت Server مدیریت بشه هم سمت Client و همینطور میتونه فقط زمان build صفحه عملیات Rendering انجام بشه یا به ازای هر بار Request یی که در زمان اجرا زده میشه .درباره Pre-renderingخب تا اینجای کار ما با مبحث Rendering آشنا شدیم ، حالا میخوام شما رو با یکی از قدرت های Nextjs  آشناتون کنم، بله درسته Pre-rendering ، این دوستمون میاد چی کار میکنه ! میاد عملیات Fetching data (واکشی داده 😁) و انتقال Component های React به صفحات HTML مون رو قبل اینکه  سمت Client برسه رو انجام میده . محشره مگه نه ?! یعنی  کاربر دیگه لازم نیست منتظر باشه تا صفحه ی مورد نظرش ، اول کامل براش Load بشه بعد تازه اونموقع بتونه کل محتوای صفحه رو ببینه ! چون الان به لطف Nextjs همه چی سمت Server مدیریت شده . حالا الان باز توضیح میدم این حالت چه فرقی با حالت های قبلی داره.تفاوت Client-Side Rendering با Pre-Renderingدر حالت معمول در React ، مرورگر شما برای اینکه بیاد UI رو بسازه، میاد یه پوسته HTML خام به همراه جاوااسکریپت های مورد نظر رو از سمت سرور میگیره بعد از اینکه جاوااسکریپت ها load شدن و همه چی گل و بلبل پیش رفت تازه اون موقع صفحه با محتواش بهتون نمایش داده میشه اگه بخوام کلی بگم ، همه چی سمت Client و مرورگر کاربر مدیریت میشه به این نوع Rendering میگن Client-side RenderingClient-side Renderingولی در نقطه ی مقابل اون یعنی Pre-rendering ، به ازای هر Request ی که میزنیم HTML صفحه مورد نظر به همراه فایل های Json و کدهای جاوااسکریپت توی اون صفحه لازم داریم، داخل Server ساخته میشه و درنهایت نتیجه سمت Clent ارسال میشه و شما توی مرورگرتون صفحه مورد نظرتون رو میبینین ، خب حالا دقیقا روال کلی کار به چه صورت هست؟!🤔Pre-Renderingشما وقتی Request میزنید تا صفحه مورد نظرتون رو ببینید، UI اولیه صفحه سمت Server ساخته میشه و به شما نمایش داده میشه (بدون جاوااسکریپت) که در اصطلاح میگن non-interactive یا غیرتعاملی ، و در نهایت بعد از اینکه جاوااسکریپت های موردنظر دانلود و بارگزاری شدن نتیجه کامل تر رو مشاهده میکنید  دراصل فرقش با Client-side Rendering توی همینه که شما در حالت قبلی تا زمانی که کل فایل ها چه HTML و جاوااسکریت و... کامل load نشن ، شما با صفحه سفید مواجه هستید و وقتی تماما فایل ها load شدن اون موقع میتونین صفحه کامل رو ببینین که درواقع همه اینه سمت مرورگر شما مدیریت میشه . حالا یه حرکت جالبی که Pre-Rendering داره اینه که ، میاد سریع یه UI اولیه از صفحه موردنظرتون رو بهتون نمایش میده تا شما نمایش اولیه صفحه رو داشته باشین در این حین میاد همزمان اون فایل های جاوااسکریپت و json و...  که توی صفحه نیاز دارید رو بارگزاری میکنه به این حرکتش میگن Hydration  که عجب حرکتیه ، شیر مادر، نان پدر حلالش 😄. بخش بعد یه خورده هیجان انگیزتر میشه ماجرا ، میخوام تک به تک متدهای Rendering رو براتون توضیح بدم 🤩. درباره CSRخب Client-side Rendering  یا به اختصار CSR به عملیات دریافت داده (Fetching data) در سمت Client گفته میشه ، حالا آیا اصلا این متد بدرد بخور هست؟🤔 باید بگم برای زمانی که صفحه تون نیازی به SEO نداره که گوگل بخواد اون رو index کنه و یا صفحه تون نیاز به Pre-Render نداشته باشه و data هاش هر لحظه بروز نمیشن ، این متد میتونه گزینه مناسبی برای این شرایطی که خدمتتون عرض کردم باشه فقط یه نکته ای که خیلی حواستون باشه اینه که این روش تاثیر زیادی میتونه روی Performance داشته باشه بخصوص روی سرعت بارگزاری صفحه تون هست چون همه چی (Fetching data) سمت Client مدیریت میشه.  خب ما به دو صورت میتونیم عملیات Fetching data رو در CSRانجام بدیم اولی اینکه با useEffectاینکار رو بکنیم یعنی به این صورت که در تصویر پایین میبینید.CSR with UseEffectروش بعدی استفاده از SWR هست که خوده Next js اون رو خیلی پیشنهاد کرده به اصطلاح گفته میشه که highly recommended هست ، خب حالا چرا! چون با استفاده از این hook میتونیم عملیات Caching  Revalidation , Focus tracking و... رو کاملا مدیریت کنیم و در واقع SWR خودش بصورت خودکار عملیات Caching رو برامون اجام میده و همینطور اگر data مون نیاز باشه که Revalidate  خودش این کار رو برامون انجام میده . از بس که این hook  گله..گل 😄 .  اگه خواستین بیشتر درباره SWR بدونین ، میتونین اینجا دربارش کامل بخونین . تصویر پایین هم Fetching data با استفاده از همین Hook هست.CSR with SWRCSRدرباره SSRحالا نقطه مقابل CSR  متد دیگه هست به نام Server-Side Rendering یا به اختصار SSR ، حالا یعنی چی نقطه ی مقابل؟! یعنی اینکه شما وقتی میخواید صفحه مورد نظرتون SEO داشته و باشه و گوگل اون رو index کنه باید از این متد استفاده کنید . حالا به چه صورت ؟ عرض میکنم خدمتتون . شما وقتی میخواید صفحه تون SSR بشه نیاز به یک تابع دارید به نام getServerSideProps وقتی که از این تابع توی صفحه مون ما export بگیریم ، Nextjs اون صفحه رو SSR در نظر میگیره به ازای هر Request ی که زده میشه این صفحه رو برامون Pre-Render میکنه.getServerSidePropsبه طور کلی این تابع در سمت server اجرا میشه و هرگز روی مروگر کاربر اجرا نخواهد شد و وقتی که شما صفحه SSR رو از طریق  next/link و یا  next/router از سمت Client درخواست (Request) میدید، Nextjs هم میاد درخواست شما رو در قالب یک Api Request  میفرسته سمت Server که شامل getServerSideProps هست . یه نکته جالب دیگه ای که لازمه بدونید اینه که Nextjs عملیات Client-bundle رو هم انجام میده به این معنی که میاد اون کدهایی که لازم نیست در سمت client باشن و bundle بشن رو حذف میکنه مثل همین تابع getServerSideProps  . برای اینکه بهتر درک کنید داستان از چه قراره خوده Nextjs یه ابزار تدارک دیده که میتونین این موردی که خدمتتون عرض کردم رو از اینجا ببینید . و این هم یه مثال دیگه از SSR برای زمانی که Request داده میشه و عملیات Pre-rendering انجام میشهSSR at Request timeمبحث جالب دیگه از SSR هست که در واقع خاصیت Caching اون هست که میتونیم با  (Cache-Control) توی header مون تعریفش کنیم و حتی با استفاده از  stale-while-revalidate. میتونیم  برای Revalidate اون، زمان بندی تعریف کنیم به این صورت که در تصویر پایین مشاهده میکنید.SSR CachingSSRدرباره SSGبرای زمانی که میخواید از Static Site Generation یا همون SSG استفاده کنید، کافیه تابع  getStaticProps رو توی صفحه تون  export کنید و وقتی Nextjs  بلافاصله ببینه تو صفحه تون از این تابع استفاده کردین فقط یکبار موقع build پروژه اون رو Pre-render میکنه برامون (بر عکس SSR که به ازای هر Request میومد برامون Pre-render رو انجام میداد. ) که به این صورت که در تصویر پایین میبینید پیاده سازی میشه SSGحالا فرقش با SSR توی چیه؟ ما صفحه ای رو SSR میکردیم که اطلاعاتش همش در حال بروز شدن بود و میخواستیم کاربر هر بار Request میزنه ، صفحه مون هم Pre-Render بشه و هم SEO گوگل اون هم حفظ بشه ولی توی SSG میگیم آقا ! ما نمیخوایم صفحه مون به ازای هر بار Request  کاربر بخواد Pre-render انجام بده چون data مون هربار تغییری نمیکنه و یکبار هم Pre-render  انجام بشه برامون کافیه و همین هم باعث میشه صفحه مون با سرعت بالاتری نمایش داده بشه که اگه گوگل ببینه سرعت صفحه بالاست ، کلی کیف میکنه و میگه درود بر شرفت ! (شوخی کردم😄 نمیگه درود به شرفت ولی خب سرعت صفحه ، فاکتور مهمیه برای گوگل ) . حالا اون یکبار Pre-render کجاست؟ اون زمانی که پروژه رو build میگیری . و اینم بهتره بدونید SEO گوگل هم برای این دوستمون هم انجام میشه .و این هم یه مثال از SSG SSG from CMSیه موضوع دیگه ای که Nextjs در خصوص SSG بهش اشاره کرده اینه که میگه  getStaticProps چون HTML که درست میکنه بصورت static هست به Request های ورودی مثل query parameters و HTTP headers دسترسی نداره و برای اینکه دسترسی داشته باشیم باید از  Middleware  استفاده کنیم .درباره ISRمتد بعدی که میخوام خدمت شما معرفی کنم ISR یا همون Incremental Static Regeneration هست . شبیه SSG هست با این تفاوت برای build  کردن کافیه بهش بگی مثلا بعد از ده ثانیه دوباره از این صفحه build  بگیر به چه صورت ؟ به این صورت که در تصویر پایین مشاهده میکنید .ISRهمونطور که مشاهده میکنید ISR تابع جدیدی نداره و همون تابع getStaticProps هست با این تفاوت که یک کلید revalidate بهش اضافه میکنید که مشخص میکنه بعد از چند ثانیه صفحه مجدد build گرفته بشه . ISRاحتمالا توی این مثال چشمتون به getStaticPath خورده و براتون سوال شده که این چیه دیگه! ? خب شما وقتی صفحه ای دارید که از Dynamic Routes و getStaticProps استفاده میکنه ، احتیاج به این تابع داره تا path هارو بصورت static تعریف کنه و Nextjs ببینه از این تابع استفاده کردین ، تمامی path هایی که مشخص کردین رو  بصورت static میاد Pre-render میکنه . و اینم یه مثال از getStaticPathgetStaticPathبرای اینکه بیشتر راجع بهش بدونین میتونین از اینجا پیگیریش کنین . خب بریم سراغ ISR خودمون ،فکر کنم تا الان متوجه شدین که ISR در واقع ترکیبی از SSR و SSG هست چون داخل SSG میتونی Pre-render سمت SSR رو داشته باشید با اضافه کردن کلید revalidate اما با رنگ و لعاب SSG .مَخلص کلامبا توجه به این مواردی که خدمتتون عرض کردم نمیتونیم به طور قطع بگیم این متد از اون یکی کامل تره و بهتره باید با توجه به نیازمون در داخل پروژه ببینیم چه متد مناسب کار ما هست ، ممکنه یه صفحه مون اصلا به SEO گوگل احتیاجی نداشته باشه میایم از CSR استفاده میکنیم ، ممکنه صفحه داشته باشیم که هر لحظه data ش update میشه مثل لیست قیمت محصولات فروشگاه و میخوایم گوگل اون رو index کنه ، پس بهتره از SSR استفاده بشه . و یا مثلا صفحه وبلاگی داریم میخوایم گوگل اونو index کنه ولی اطلاعاتش دیر به دیر update میشه، خب میایم از SSG استفاده میکنیم و یا میخوایم ترکیبی عمل کنیم یعنی صفحه مون میخوایم SSG باشه ولی بعد از یه مدت خاص Pre-render بشه اونجا هم میایم از ISR استفاده میکنیم و تمام. امیدوارم از خوندن این مقاله نهایت استفاده رو کرده باشید، روز و روزگارتون خوش.</description><category>محسن محمدی رهنما</category><author>محسن محمدی رهنما</author><pubDate>Sat, 05 Nov 2022 23:12:40 +0330</pubDate></item></channel></rss>