beardy developer
beardy developer
خواندن ۷ دقیقه·۳ سال پیش

استفاده از apollo-client به عنوان state manager(قسمت دوم)

قبل از شروع، اگر قسمت اول رو مطالعه نکردید حتما اینکار رو بکنید و برگردید:

https://virgool.io/@mohammad.mirzaei/%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-apollo-client-%D8%A8%D9%87-%D8%B9%D9%86%D9%88%D8%A7%D9%86-state-manager%D9%82%D8%B3%D9%85%D8%AA-%D8%A7%D9%88%D9%84-i76qhrt5okfd

بریم سراغ قسمت دوم مقاله یا همون هندل کردن client local state هامون با آپولوی عزیز.

قرار نیست به بحث های قبلی پرش داشته باشیم و یک راست میریم سراغ راه های مختلف کنترل کردن استیت های لوکالمون :

1- Local only fields

ساده ترین روش برای ذخیره و دسترسی مجدد به یک استیت لوکال همین روش هست.

تو این روش همه چیز شبیه یه کوئری عادی هست با این تفاوت که با قرار دادن یه directive به اسم client@ جلوی فیلد مورد نظر از کوئریمون، آپولو دیگه برای دریافت اون ریکوئستی به سرور نمیزنه و میره از کش خودش میخونه و در نتیجه همه چیز سمت فرانت هندل میشه.

به عنوان مثال میخوایم استیت مربوط به dark mode اپ رو ذخیره و بعدا آپدیت کنیم. بریم سراغش:

اولین کاری که باید بکنیم نوشتن کوئریمون هست :

همونطور که گفتم با این directive آپولو میفهمه که این یه فیلد لوکال هست.
به نظرتون الان میتونیم از این کوئری استفاده کنیم و مقدار isDarkMode رو بگیریم ؟

قطعا نه.
اما چرا ؟ مشکل اینه که این فیلد مقدار اولیه ای نداره و عملا اگر بخوایم بخونیمش یه undefined میخوره تو صورتمون.
راه حل چیه ؟

راه حل store کردن مقدار پیش فرض این فیلد داخل cache آپولو هست تا یه مقدار اولیه ای داشته باشیم موقع لود اپمون و به این مشکل نخوریم.
برای اینکار 2 تا روش داریم :

یه روش اینه که مستقیما داخل InMemoryCache کانفیگ cache که به client پاس دادیم مقدار دهیش کنیم ( قرار نیست اینجا آپولو رو یاد بگیریم و اگر نمیدونید درباره چی حرف میزنم یه سری به داک آپولو بزنید ) :

*تو عکس بالا typePolicies به ما اجازه دسترسی، آپدیت و تغییر فیلد هامون رو بسته به نیاز ها و شرایط مختلفی که داریم میده.
هر فیلدی رو که بخوایم تغییر بدیم، باید داخل آبجکت fields که داخل آبجکتی همنام تایپی قرار داره که شامل فیلد مورد نظر و هدف ما هست اینکار رو انجام بدیم.
تو مثال ما، فیلد isDarkMode داخل تایپ Query هست و از همین طریق میتونیم بهش دسترسی پیدا کنیم و کاستومایزش کنیم.
* این تایپ ها جزو meta data های graphQl هستن و ربطی به آپولو ندارن. کارشون هم دسته بندی فیلد ها و یه سری کار های دیگه هست.
تو مثال ما چون صرفا یه کوئری ساده بدون ست کردن متا دیتا زده شده، فیلد ما زیرمجموعه تایپ Query هستن. اما اگر کوئری ما از سمت سرور دیتا بگیره، برای دسترسی به تایپ فیلد ها میتونید به typename__ که معمولا همراه ریسپانس میاد و یه متادیتا هست مراجعه کنید. مثلا تایپ response زیر Episode هست که ازش یه لاگ گرفتم داخل کنسول :

console log
console log


و اما یه روش دیگمون برای مقدار دهی هم اینه که cache instance آپولو رو rewrite کنیم و به دیتای کوئری که داریم مقدار دیفالت بدیم :


در هر دو روش، حالا مقدار اولیه فیلد ما false هست و دیگه آندفایند دریافت نمیکنیم :))

نکته قابل توجه اینه که میتونیم این فیلد های local only رو درکنار فیلد های سرور هم قرار بدیم و همزمان هر دورو داخل کوئریمون بخونیم.
این کار هم دقیقا مثل حرکتی هست که بالاتر زدیم و تنها تفاوتی که داره اینه که فیلدی که داریم همسایه فیلد های دیگه میشه :

حالا در کنار فیلد allEpisodes که از سمت سرور میاد، به isWatchable هم دسترسی داریم که سمت خودمون مقدار دهی میشه و میتونیم با کمک اون مشخص کنیم که فلان اپیزود قابل مشاهده هست یا نه.
برای مقدار دهی هم میتونید از یکی از دو روش بالا ( پیشنهادم روش دوم هست ) استفاده کنید.
( لازم به ذکرم که توی روش اول میتونید فیلد های لوکال رو بر اساس ریسپانس سرور مقدار دهی کنید اما بهش نمیپردازیم چون بحث تخصصی تر و حجیم تر میشه؛ در صورت تمایل یه سری به داک آپولو بزنید در این زمینه )


آپدیت کردن فیلد ها

اگر بخوایم dark mode رو فعال کنیم چیکار کنیم ؟ چطور میتونیم این مقدار رو به true تغییر بدیم ؟
خیلی راحت؛ فقط کافیه مجددا به cache آپولو دسترسی پیدا کنیم و مقدار جدید رو جایگزین مقدار قبلی کنیم.
*(در نظر داشته باشید که برای آپدیت کردن مستقیم فیلد هامون بعد از کلیک روی یک دکمه یا مورد مشابه، باید طبق روش دوم پیش بریم تا با instance در اختیارمون، هرجایی از اپ بتونیم عملیات باز نویسی و آپدیت رو انجام بدیم؛ در غیر اینصورت قادر به آپدیت کردن فیلد هامون نخواهیم بود در صورت استفاده از روش اول )*
خب حالا چطوری آپدیت رو انجام بدیم؟ اینطوری :

توی عکس بالا بعد از دریافت مقدار اولیه یا current data، بعد از کلیک روی دکمه مورد نظر شروع به rewrite کردن client میکنیم و مقدار قبلی رو reverse و تبدیل به true میکنیم؛ حالا باید تم دارک ما فعال بشه :)


2- Reactive Variables

این روش، روش مورد علاقه من برای ذخیره و کار با استیت های لوکال تو آپولو هست. خیلی تر و تمیز و مااااهه. بریم باهاش آشنا بشیم که شما هم عاشقش بشید :)


کمی بالا تر گفتم که درصورت مقدار دهی فیلد هامون داخل typePolicies، قادر به آپدیت کردن اونها نیستیم در آینده و همیشه ثابت هستن. این اصلا خوب نیست چون عملا بدردمون نمیخورن و الکی این همه راهو اومدیم.
ما به عنوان یه state manager انتظار داریم که مقادیری که ذخیره کردیم قابل تغییر باشن.
اما این مشکل هم حل شدنیه. چطوری؟
با یکی دیگه از روش های store کردن آپولو به اسم reactive variable.


همون طور که از اسمش پیداست، تو این روش مقادیر واکنش گرا و قابل تغییری خواهیم داشت به عنوان مقدار فیلد هایی که داخل typePolicies مقدار دهی کردیم. و بسته به اتفاقاتی که تو اپ ما میفته میتونیم تغییرشون بدیم.
مثال زیر رو که تو بخش اول هم داشتیمش دوباره در نظر بگیرید :

همون طور که قبلا هم گفته شد، مقدار اولیه dark mode ما false هست، اما غیر قابل تغییر و ایستا هست. یعنی نمیتونیم این false رو تبدیل به true یا هرچیز دیگه ای بکنیم تا تم ما عوض بشه ( و مجبور شدیم از روش rewrite کردن cache استفاده کنیم ).
حالا با کمک reactive variable ها میتونیم این مقدار رو داینامیک و قابل تغییر در نظر بگیریم.
قبل از هرچیزی برای تمیز کاری بیشتر، قراره یه فایل مجزا برای این variable ها تعبیه کنیم و همه رو اونجا نگهشون داریم ( درست مثل کاری که تو ریداکس میکردیم و برای اکشن ها و استور ها و ... فایل مجزا میساختیم ).
اسم فایلتون رو store یا storage یا هرچیزی که عشقتون میکشه بزارید :) و داخلش :

حالا دوباره برمیگردیم سراغ cache مون :

تا اینجای کار فقط مقدار اولیه که همون false هست رو یه مدل دیگه ست کردیم. پس این reactive بودنش کجاست ؟

برای آپدیت کردن، فقط کافیه هرجایی که لازم داریم ( مثلا بعد از کلیک روی یه دکمه ) مقدار جدید رو پاس بدیم به variable مورد نظرمون( حتی میتونیم مقدار قبلیش رو هم ازش بگیریم و طبق اون تغییرش بدیم ) :

ایزی ایزی تامام تامام :) حالا یه ریداکس بدون نیاز به ریداکس داریم تو آپولومون ( جواد خیابانی )


ساختار پروژه

این بخش از مقاله زیاد ربطی به آپولو نداره و بیشتر بحث تمیز کاری و با شخصیت بودن کد هامونه :دی
اگه به کد های بالا و نحوه ارتباطشون به هم دیگه دقت کرده باشین متوجه میشین که زیادی بهم متصل هستن و اگر بخوایم طبق روال بالا پیش بریم خیلی گند بالا میاریم و کدمونو خودمون هم نمیتونیم بخونیم اگر مقیاس پروژه کمی بزرگ تر بشه.
برای همین تصمیم گرفتم یه structure یا ساختار پیشنهادی بهتون ارائه بدم که اگر دوست داشتین طبق اون پیکربندی کنید فایل های مربوطه رو:

  • فایل store.js : این فایل محل نگهداری reactive variable هامون هست تا دم دست تر باشن و جایی رو شلوغ نکنن. ( حتما اکسپورتشون کنید چون لازمشون داریم جاهای دیگه )
  • فایل cache.js : این فایل هم فایل اصلی ما و محل کانفیگ کردن مموری و کش آپولو هست. پس کانفیگ cache رو منتقل کنید توی این فایل و حتما اکسپورتش کنید. البته یادتون نره که چون به variable های فایل بالایی نیاز دارید، میتونید همینجا اول فایل ایمپورتشون کنید و داخل cache استفادشون کنید.
  • فایل mutations.js یا actions.js : این فایل هم مختص نگهداری فانکشن هایی هست که مسئول آپدیت کردن variable هامون هستن تا داخل کامپوننت هامون پخش و پلا نشن و منسجم و در دسترس باشن.
    برای استفاده از این فانکشن ها کافیه اکسپورتشون کنید و هرجایی که خواستید ایمپورت و کالشون کنید و حتی بهشون پارامتر پاس بدید و داخل اکشن دریافت کنید و ... کارای دیگه.
    ( یادتون نره برای آپدیت کردن variable ها بهشون نیاز دارید و لازمه که از فایل store ایمپورتشون کنید )

خب این هم از بخش دوم مقاله و بررسی local state های آپولو. امیدوارم بدردتون خورده باشه و تونسته باشم چیزی به دانشتون اضافه کنم.
تا یه مقاله توپ دیگه مواظب خودتون و استیت هاتون باشید. ( لایک هم یادتون نره )







ریداکسreduxapolloapollo clientreact
اگه خدا بخواد برنامه نویس فرانت اند
شاید از این پست‌ها خوشتان بیاید