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

اومدم براتون از شگفتی های یه لایبرری خفن برای کار با graphQl بگم که علاوه بر فچ کردن کوئری های سمت سرورتون و کش کردن اون ها، میتونه نقش یه global state manager رو هم بازی کنه تا دیگه نیازی به ریداکس و ... برای استیت های لوکالتون هم نداشته باشید چه رسد به سرور استیت هاتون.اگر شما هم داخل پروژه‌تون با graphQl سر و کار دارید و سرورتون هم با apollo-server سر و کار داره، بهترین گزینه برای سرو کله زدنتون با کوئری ها apollo-client هست ( چقدر سرو کله )بجز آپولو از چی میتونیم استفاده کنیم ؟توی شرایط عادی و سنتی اگر بخواید دیتایی که از سرور دریافت میکنید یا استیت های local خودتون رو داخل اپلیکیشنتون بین تمام کامپوننت های یو آی share کنید و از هرجای اپ بتونید دیتای قبلی رو تغییر بدید و جایگزین قبلی ها بکنید، مجبورید دست به دامان گلوبال استیت منیجر ها بشید و گاها برای caching از ابزار های کشینگ اون ها استفاده کنید که اسم بعضیاشون رو تریلی هم نمیکشه :دیریداکس علیه السلامریداکس چیه و چطوری کار میکنه ؟ یکی از این اسم گنده ها و گولاخ ها redux هست که کمتر کسی پیدا میشه که اسمشو نشنیده باشه تاحالا.ریداکس یک store container جاوا اسکریپتی هست که وظیفه ذخیره سازی و سازمان دهی استیت های اپلیکیشن و به بیانی هندل کردن یک state management رو به عهده داره. عملکرد ریداکس کمی پیجیده هست و به المان های زیادی وابسته هست که میخوایم بررسیشون کنیم ( البته قرار نیست آموزشی ریداکس رو هم بنویسیم و با مفهوم و تعریف و کانسپت اجزای مختلفش چیه ).عکس بالا جریان کلی کارکرد ریداکس رو نشون میده که به ترتیب شامل مراحل زیر هست:۱- یک action از کامپوننت یا UI ارسال یا به اصطلاح dispatch میشه که شامل اطلاعات مربوط به بلایی هست که قراره سر state بیاد ( میتونه ذخیره سازی یا آپدیت و یا حتی خالی کردن اون باشه )۲- اگر اکشن یه اکشن عادی بود که فقط قرار بود اسم ممد رو به اصغر تغییر بده زیاد مشکل ساز نبود؛اما وقتی قراره بصورت async چیزی رو از سرور بگیره و بعد از رسیدن پاسخ اون بره سمت store تا اون پاسخ رو جایگزین اسم ممد بکنه اینجاست که middleware وارد عمل میشه و بین اکشن و reducer قرار میگیره تا منتظر فچ شدن دیتا بمونه و بعد از اون اکشن مربوطه رو به همراه دیتای گرفته شده از سرور دیسپچ کنه.۳- و اما reducer عزیز که وظیفه تغییر و normalize کردن استیت هارو به عهده داره( البته این خودمون هستیم که این کار رو انجام میدیم )۴- در نهایت state به روز دوباره به کامپوننت یا UI ما برمیگرده و آماده استفاده میشه.تا اینجای کار با یه حساب سر انگشتی اگر بخوایم عکس بالا رو داخل کد هامون پیاده بکنیم همه چیز وابسه به فایل یا دایرکتوری اکشن ها، ردیوسر ها و فایل کانفیگ store خواهد بود( به علاوه هوک های ریداکس برای گرفتن این دیتاها داخل کامپوننت هامون )حالا موارد بالا رو یادتون باشه تا بریم یه مثال واقعی از ریداکس و فچ کردن دیتای async با middleware هاش رو ببینیم.( دیتا مربوط به کوئری graphQl هست ها )CODE-1بصورت خلاصه توی middleware بالا دیتا رو از کوئری GET_USER دریافت میکنیم و بعد اون رو به اکشن های SUCCESS و ERROR پاس میدیم تا سمت ردیوسر بتونیم استیت های مربوط بهشون رو آپدیت کنیم( مثلا یه لودینگ ست کنیم یا پیغام خطا نشون بدیم و ...)درواقع استیت isLoading در ابتدا true هست و بعد از گرفتن دیتا false میشه تا بتونیم داخل کامپوننت یه لودینگی ست بکنیم :(تازه همه اینا به کنار اگر بخوایم دیتایی که از سرور گرفتیم رو cache کنیم مجبوریم از ابزار های دیگه ای مثل redux-persist استفاده کنیم و کلی کانفیگ بنویسیم براش تا بتونیم استیت های سمت سرور رو کش کنیم...ریداکس که کار میکنه :/ پس چرا apollo ?بله ریداکس کار میکنه... به خوبی هم کار میکنه و مشکلی وجود نداره.البته تا وقتی apollo-client عرض اندام نکنه که وقتی بکنه ریداکس دیگه حرفی برای زدن توی پروژه هایی که با graphQl سروکار دارن نداره.آپولو یه لایبرری state manager و cache enginer همه جانبه جاوا اسکریپتی هست که به ما اجازه هندل همزمان استیت های لوکال و ریموت رو میده.به کمک آپولو میتونیم دیتای مورد نیازمون رو دریافت، کش، و تغییر بدیم اون هم با آپدیت خودکار UI مربوطه.چرا apollo ?سادگی در استفاده : آپولو سینتکس و لاجیک خیلی ساده ای داره و در حالت عادی با یکی دو خط کد میره دیتا رو همراه وضعیت هاش بر میداره میاره.دیتا فچینگ declarative : آپولو به طور معجزه آسا و هوشمندانه ای وضعیت های فچینگ رو خودش برامون track میکنه و برمیگردونه؛ یعنی دیگه لازم نیست دوتا اکشن و کلی کد و شرط برای گرفتن loading و error بنویسیم و خود آپولو این کارو برامون انجام میده :)کشینگ ساده : آپولو سیستم caching قدرتمند و باهوشی داره که با چند خط کد قابل پیاده سازی هست و اونقدر باهوشه که اگر یک کوئری رو برای بار دوم ارسال کنید دیگه برای دریافت دیتاش سمت سرور نمیره و مستقیما از cache خونده میشه :)نورمالایز خودکار : برعکس ریداکس که خودمون مسئول نورمالایز کردن - نورمالایز یعنی مرتب سازی فیلد ها- و همگام سازی استیت هامون هستیم آپولو حتی این بار رو هم از دوش ما برداشته و خودش اینکار رو برامون انجام میده( لایبرری انقدر با شعور آخه؟ )ترکیب دیتای لوکال و ریموت : آپولو این قابلیت رو برامون فراهم میکنه که در کنار فیلد های سرور کوئریمون فیلد های لوکال هم بنویسیم که کاملا سمت فرانت نگهداری میشن و ربطی به بک ندارن.یعنی آپولو علاوه بر اینکه یه لایبرری برای فچ کردن کوئری هامون هست میتونه یه لوکال استیت منیجر عالی هم باشه و هیبریدی عمل کنه برامون.ضمنا آپولو قابلیت کار با rest رو هم داره که نیازی به ابزار دیگه ای مثل axios هم نداشته باشید حتی.آپولو چه تفاوت هایی با ریداکس داره ؟Redux vs Apolloتوی آپولو دیگه خبری از reducer و action و store config و این داستان ها نیست. ایزی ایزی :)تمامی وظایف اکشن هارو hook ها و گاها متد های خوشگلش انجام میدن که هم میتونن دیتا رو فچ کنن و هم دیتای سمت سرور رو mutate کنن.چیزی به اسم middleware دیگه معنی نداره و همه چیز async عمل میکنه.تمامی وظایف reducer ها و تغییرات استیت ها و نورمالایز اون ها رو هم خود آپولو بصورت خودکار برامون انجام میده و نیازی نیست دستمونو آلوده کنیم.و اما داخل آپولو بجای یک store container همه چیز مستقیما داخل cache مرورگر هندل میشه و از هرجای اپ میشه به راحتی دیتارو مستقیما از کش دریافت کنیم.بریم ببینیم آپولو چطوری کار میکنه:مطابق شکل بالا مراحل زیر انجام میشن : ۱- اولین کار نوشتن کوئری سمت UI هست که شامل فیلد های درخواستی از سرور هست.۲- آپولو این کوئری رو سمت سرور میفرسته تا دیتای اون رو دریافت بکنه ( بالاتر هم گفتم که آپولو میتونه همزمان با api های rest هم کار بکنه ).۳- بعد از دریافت دیتای سرور نوبت به دیتای local میرسه که دریافت یا اصطلاحا read بشه( دیتای local-only باید منتظر دیتای ریموت بمونه)۴- در نهایت دیتا به UI ارسال میشه و کامپوننت های مربوطه آپدیت میشن.حالا اگر موارد بالا رو در نظر بگیریم و بخوایم ببینیم مثال CODE-1 بالا که با ریداکس نوشته شده بود چطوری با آپولو به سادگی نوشته میشه به مثال زیر توجه کنید و سر به بیابان بزارید :)CODE-2همون طور که بالا تر گفتم حتی استیت های فچینگ کوئری هم بصورت خودکار در اختیارمون قرار میگیرن و فقط با یک خط کد و به کمک هوک useQuery آپولو از شر ده ها خط اکشن نویسی و شرط گذاری و میدلویر گذاری خلاص شدیم *ــــ*( البته فراموش نکنید که کوئری ها برای اسفاده با آپولو باید داخل تمپلیت gql خود آپولو نوشته بشن که در کنار همین useQuery میشه ایمپورت و استفادش کرد )تا اینجای کار فقط با استیت های سمت سرور و ریموت کار کردیم و وارد بحث local state ها و انواع اونها و همینطور بررسی عملکرد cashing نشدیم چون یکم طولانی شد مقاله...تا همینجا داشته باشید مقاله رو به زودی توی قسمت دوم میریم سراغ این مباحث و خیلی بیشتر با آپولو حال میکنیم. 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%AF%D9%88%D9%85-kha6ed4ytddr