<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های حسین شیره جونی</title>
        <link>https://virgool.io/feed/@shirejoni</link>
        <description>Software Engineer | مثل اینکه کد میزنم!</description>
        <language>fa</language>
        <pubDate>2026-06-16 10:09:47</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/4555/avatar/tR5qXX.jpg?height=120&amp;width=120</url>
            <title>حسین شیره جونی</title>
            <link>https://virgool.io/@shirejoni</link>
        </image>

                    <item>
                <title>راهنمای کامل Memo در React</title>
                <link>https://virgool.io/@shirejoni/%D8%B1%D8%A7%D9%87%D9%86%D9%85%D8%A7%DB%8C-%DA%A9%D8%A7%D9%85%D9%84-memo-%D8%AF%D8%B1-react-wlfk66h7nrpm</link>
                <description>در این مقاله به بررسی memoization می‌پردازیم. memoization یک تکنیک قدرتمند است که می‌تواند باعث بهبود عملکرد کد شود. اما مهم است که این تکنیک را به درستی استفاده کنید. این مقاله طولانی است، اما برای درک درست این تکنیک، ارزش خواندن دارد.تعریف Memoizationترجمه اش در فارسی &quot;به خاطر سپردن&quot; می شود، که یکی از تکنیک‌های رایج بهینه‌سازی در برنامه‌نویسی است. به این صورت که تابع در اولین بار که صدا زده می‌شود، خروجی خود را محاسبه می‌کند و سپس آن را در حافظه ذخیره می‌کند. در دفعات بعدی صدا زدن تابع، به جای محاسبه مجدد خروجی، از خروجی ذخیره شده قبلی استفاده می‌شود.فلوچارت Memoizationپیاده‌سازی توابع Memoization معمولا به دو روش انجام می‌شود:روش اول: ذخیره‌سازی آخرین خروجی تابع است. در این روش، تابع در هنگام فراخوانی خروجی خود را محاسبه و در حافظه ذخیره میکند. در دفعه‌ی بعدی که تابع با همان آرگومان فراخوانی می‌شود، به جای محاسبه مجدد، از خروجی ذخیره شده قبلی استفاده می‌شود. در صورتی که تابع با argument متفاوتی صدا زده شود مقدار خروجی دوباره محاسبه میگردد و جایگزین مقدار قبلی می شود.روش اول memoizationمزیت روش اول این است که همیشه یک خانه از حافظه را ذخیره میکند ولی درصورتی که تابع هر بار با ورودی های متفاوتی صدا زده شود مجبور به محاسبه مجدد می شود.روش دوم: در این روش، برای هر آرگومان ورودی که تابع را فراخوانی می‌کند، یک key ایجاد می‌شود و output تابع با آن key ذخیره می‌شود. در دفعات بعدی که تابع با همان آرگومان فراخوانی می‌شود، ابتدا key مربوط به آن آرگومان بررسی می‌شود. در صورتی که key وجود داشته باشد، خروجی تابع از حافظه برگردانده می‌شود. در غیر این صورت، تابع محاسبه می‌شود و خروجی آن ذخیره می‌شود.روش دوم memiozationبه دلیل اینکه این روش به ازای هر آرگومان متفاوت، خروجی تابع را ذخیره می‌کند، در استفاده از آن باید میزان فضای اشغال شده حافظه را در نظر گرفت. در ادامه پیاده سازی تابع memoize با استفاده از هر دو روش را مشاهده میکنید:پیاده سازی روش اولپیاده سازی روش دوممهمترین نکته ای که باید همیشه در ذهنتان باشد:مموایز کردن یک وسیله برای پایین آوردن هزینه زمان تابع در عوض افزایش هزینه فضا است؛ که به این معنی است که توابع مموایز شده برای افزایش سرعت در عوض استفادهٔ بیشتر از حافظه کامپیوتر بهینه می‌شوند.کاربرد های Memoization در Reactکاربرد های Memoization در React برای جلوگیری از رندر مجدد کامپوننت ها، محاسبه مقدار تابع و حفظ رفرنس قبلی تابع یا Object است.استفاده از React.memoبا memo شما میتوانید از رندر مجدد کامپوننت جلوگیری کنید. همچنین، می‌توانید با استفاده از تابع arePropsEqual تعیین کنید که کامپوننت با تغییر چه props‌هایی رندر شود. کد زیر را در نظر بگیرید:رندر کامپوننت ExpensiveTree سنگین است و زمان زیادی طول می‌کشد تا این کامپوننت رندر شود. در کامپوننت App، استیت counter وجود دارد که با کلیک بر روی دکمه، باعث افزایش counter و رندر مجدد App می‌شود. همانطور که می‌دانید، در فرایند رندر کامپوننت، فرزندان آن کامپوننت نیز مجددا رندر می‌شوند. در حالی که ExpensiveTree مستقل از مقدار counter هست و نیازی به رندر مجدد ندارد با استفاده از memo میتوان جلوی رندر آن را گرفت.تابع memo یک کامپوننت جدید React بازگردانده است. عملکرد آن مانند کامپوننتی است که به memo ارائه شده است، با این تفاوت که هنگام رندر کامپوننت پدر، فقط در صورتی که props های کامپوننت فرزند تغییر کرده باشد، آن را رندر میکند.بدون استفاده از memoبا استفاده از memoتابع arePropsEqualمعمولاً نیازی نیست از این تابع استفاده کنید، زیرا مقدار پیش فرض React کافی است. این تابع props قبلی و فعلی کامپوننت را به عنوان ورودی می‌گیرد و وظیفه آن مقایسهٔ این دو مقدار است. تابع پیش فرض React تمامی مقادیر props را با استفاده از object.is (که معادل === است) مقایسه می‌کند. اگر یکی از property‌ها تغییر کرده باشد، تابع مقدار false را برمی‌گرداند و کامپوننت مجدداً رندر می‌شود. شما می‌توانید این تابع را تغییر دهید تا کامپوننت فقط در صورتی که یک property خاص تغییر کرده باشد، مجدداً رندر شود.استفاده از useMemoبا استفاده از این هوک می‌توانید مقدار یک تابع را محاسبه کنید و برای رندرهای بعدی از مقدار کش شدهٔ آن تابع استفاده کنید. این کار مشابه روش اول memization است که در ابتدای مقاله به آن اشاره کردیم. توجه داشته باشید که کالبکی که به useMemo می‌دهید نیازی به آرگومان ورودی ندارد. useMemo در هنگام mounting (رندر اول) این تابع را صدا می‌زند و مقدار آن را کش می‌کند. آرگومان دوم useMemo یک آرایه از وابستگی‌ها (dependency) است که تعیین می‌کند در صورت تغییر کدام آیتم‌های کامپوننت، مقدار تابع دوباره محاسبه و کش شود.محاسبه اعداد فرد بدون useMemoدر تصویر بالا، کامپوننت ExpensiveList یک لیست ۱۰۰,۰۰۰ تایی از اعداد را فیلتر می‌کند و تعداد اعداد فرد را در صفحه چاپ می‌کند. این محاسبه سنگین در هر بار رندر شدن کامپوننت انجام می‌شود. با این حال، اگر لیست تغییر نکند، نیازی به محاسبه مجدد این مقدار نیست.محاسبه اعداد فرد با استفاده از useMemoدر تصویر بالا، کامپوننت ExpensiveList یک لیست ۱۰۰,۰۰۰ تایی از اعداد را فیلتر می‌کند و لیست جدید را کش می‌کند. سپس، تعداد اعداد فرد را در صفحه چاپ می‌کند. در رندرهای بعدی، کامپوننت تعداد را از لیست کش شده محاسبه می‌کند. در ادامه، تفاوت زمانی این بهبود را مشاهده می‌کنید.محاسبه اعداد فرد بدون useMemoمحاسبه اعداد فرد با استفاده از useMemoتوجه کنید مقدار اولیه محاسبه شده تفاوت زیادی باهم ندارند در نتیجه: هوک useMemo باعث سریع‌تر شدن رندر اولیه نمی‌شود. این فقط به شما کمک می‌کند تا کارهای غیر‌ضروری را در رندر مجدد حذف کنید.کد دوم (محاسبه اعداد فرد با استفاده از useMemo) یک مشکل دارد: در صورتی که لیست ما، لیست داینامیک بود و اعداد آن تغییر می‌کرد، مقدار جدید محاسبه نمی‌شد. برای رفع این مشکل، باید لیست جدید را به عنوان dependency به useMemo اضافه کنیم. مانند تصویر زیر:آرایه‌ی وابستگی(dependency array)وابستگی (dependency) یک آرایه از مقادیر یا متغیرهای کامپوننت است که معمولاً به عنوان آرگومان دوم به بعضی از هوک‌های React مانند useEffect، useMemo و ... داده می‌شود. React در هر رندر، با مقایسه مقادیر این آرایه با مقادیر رندر قبلی، متوجه تغییرات می‌شود و در صورت تغییر، افکت یا محاسبه کامپوننت را دوباره اجرا می‌کند. توجه داشته باشید که این مقایسه با استفاده از Object.is (مانند ===) انجام می‌شود. بنابراین، اگر یک آبجکت را به عنوان آیتم این لیست در نظر بگیرید، فقط در صورتی که رفرنس آنها برابر باشد، React تشخیص می‌دهد که آبجکت تغییر نکرده است.Object.isهمانطور که در تصویر بالا مشاهده می‌کنید، متغیرهای a و b هر دو مقدار یک آبجکت خالی را دارند، اما به دلیل اینکه ارجاع(reference) آنها متفاوت است، Object.is() مقدار false را برمی‌گرداند. در مقابل، متغیرهای a و c به یک آبجکت در حافظه اشاره می‌کنند، بنابراین برابر هستند و Object.is() مقدار true را برمی‌گرداند.در کد بالا، آرایه items که به کامپوننت Tab داده شده است، در هر بار رندر دوباره ساخته می‌شود. این کار باعث می‌شود که رفرنس آرایه تغییر کند. در نتیجه، اگر این آرایه به عنوان dependency در یک کامپوننت فرزند استفاده شود، همواره نتیجه مقایسه Object.is برابر با false خواهد بود. بنابراین، React افکت یا تابع هوک مربوطه را دوباره اجرا می‌کند. برای مثال:در نمونه کد بالا، به دلیل اینکه آرایه props.items در هر بار رندر، رفرنس آن تغییر می‌کند، مقدار tabItems نیز هر بار محاسبه می‌شود.مواردی مانند نمونه بالا زیاد اتفاق می‌افتند. بسته به شرایط، می‌توان آرایه را به بیرون از کامپوننت منتقل کرد، به درون کامپوننت منتقل کرد یا با استفاده از هوک useMemo، رفرنس آرایه را برای رندرهای بعدی یکسان نگه داشت. در ادامه، نمونه منتقل کردن آرایه به بیرون از کامپوننت را میبیند:از آنجایی که آرایه items به صورت استاتیک مقداردهی شده است و تغییر نمی‌کند، می‌توان آن را به بیرون از کامپوننت منتقل کرد. در این صورت، آرایه فقط در هنگام import ماژول ساخته می‌شود و رفرنس آن در طول برنامه تغییر نمی‌کند. بنابراین، useMemo فقط در رندر اول مقدار آرایه را محاسبه می‌کند.استفاده از useCallbackبا استفاده از هوک useCallback می‌توان رفرنس یک تابع را در بین رندرها نگهداری کرد. این کار مشابه روش اول memoization است، با این تفاوت که مقداری که باید کش شود، رفرنس یک تابع است. تابعی که به useCallback می‌دهید صدا زده نمی‌شود، بلکه رفرنس آن تابع نگهداری می‌شود. این کار می‌تواند برای مواقعی که تابعی را به عنوان dependency در آرایه وابستگی قرار می‌دهید یا به عنوان property کامپوننت پاس می‌دهید، مفید باشد. آرگومان دوم useCallback یک آرایه از وابستگی‌ها (dependency) است که تعیین می‌کند در صورت تغییر کدام آیتم‌های کامپوننت، رفرنس جدید نگهداری شود.بدون استفاده از useCallbackکد بالا باعث می‌شود که با هر بار رندر شدن کامپوننت، تابع makeHeavyRequest جدیدی تعریف شود. در نتیجه، رفرنس این تابع متفاوت است و useEffect دوباره صدا زده می‌شود.بدون استفاده از useCallbackاگر در کد بالا از useCallback استفاده کنیم:با استفاده از useCallbackدر کد بالا، رفرنس تابع makeHeavyRequest در بین رندرها یکسان باقی می‌ماند. از آنجایی که آرایه وابستگی useEffect نیز در بین رندرها یکسان است، useEffect فقط یک بار اجرا می‌شود.با استفاده از useCallbackچرا نباید در همه جا استفاده کنیماگر استفاده از memo در همه جا منطقی بود، React تمامی کامپوننت‌ها و هوک‌های خود را با همین پیشفرض توسعه می‌داد.کاهش خوانایی کدهنگام خواندن کدی که بخشی از آن توسط useMemo یا useCallback احاطه شده است، باید به دو نکته توجه کنید:بررسی Dependencyها: باید بررسی کنید که کدام متغیرها یا توابع در dependency ها قرار گرفته‌اند. و چه زمانی این مقادیر تغییر میکنند.بررسی هنگام استفاده: هنگام استفاده از خروجی این هوک‌ها، باید توجه کنید که از مقدار جدید یا مقدار کش شده استفاده می‌کند. یعنی دقت به dependency ها نه تنها در زمان نوشتن، در زمان استفاده نیز باید انجام داد.فرایند توسعه را پیچیده میکندهنگام استفاده از memoization باید دقت کنیم که مقادیر آرایه وابستگی به درستی تغییر کند. مخصوصاً در مواردی که از آبجکت‌ها، توابع یا آرایه‌ها به عنوان dependency استفاده می‌کنیم. این توجه فقط برای نوشتن اولیه کد نیست، بلکه با هر بار تغییر نیز باید به این موضوع دقت شود. نمونه مثال زیر:در مثال بالا، اگر استایل را به عنوان props به کامپوننت ExpensiveTree پاس دهیم، به دلیل اینکه آبجکت style در هر رندر ساخته می شود، کامپوننت ExpensiveTree نیز در هر رندر مجدداً رندر می‌شود. این اتفاق باعث می‌شود که memo کاربرد خود را از دست بدهد. برای جلوگیری از این اتفاق، می‌توان از useMemo برای نگهداری مقدار style استفاده کرد.ولی با این تغییر، هنگام توسعه در آینده باید به هر دو بخش، Props های کامپوننت ExpensiveTree و آرایه وابستگی useMemo دقت کرد و خیلی ساده در ریفکتور بعدی، میتواند این ساختار شکسته شود مثلا اگر در ریفکتور بعدی، تصمیم گرفته شود style از کامپوننت parent گرفته شود، عملا استفاده از useMemo را بیهوده می‌کند. مانند:احتمال حذف نشدن از حافظههنگامی که از هوک‌های useMemo یا useCallback استفاده می‌کنیم، مقدار اولیه آن‌ها در حافظه باقی می‌ماند، حتی اگر در رندرهای بعدی تغییر نکنند. این به این دلیل است که Garbage Collector نمی‌تواند مقدار اولیه را از حافظه پاک کند، زیرا هنوز به آن از طریق dependency ها یا سایر objects اشاره وجود دارد. اگر این مقدار اولیه در کامپوننت‌های دیگر یا objects دیگری که لایف تایم بیشتری از کامپوننت دارند استفاده شود، می‌تواند باعث memory leak شود. البته این مورد را نمیتوان فقط به این هوک‌ها اختصاص داد ولی به دلیل نحوه استفاده شون احتمال رخدادشون بیشتر است.بعضی از راه های جایگزیندر هنگام توسعه در هر بخش از کد که تصمیم به استفاده از memoization گرفتید قبل از آن به راه حل های زیر نیز فکر کنید:انتقال استیت به درون کامپوننتمی‌توان استیتی که باعث رندر مجدد کامپوننت می‌شود را به یک کامپوننت جداگانه منتقل کرد. به عنوان مثال، در کد ExpensiveTree می‌توان استیت counter را به یک کامپوننت جداگانه منتقل کرد:با این تغییر با اپدیت شدن مقدار counter، فقط کامپوننت  Counter رندر می شود.انتقال محتوا به بالا (Lift Content Up)اگر کامپوننت ما به نحوی بود که امکان انتقال به کامپوننت جداگانه را نداشت مانند مثال زیر:می‌توان کامپوننت سنگین را به عنوان prop به آن کامپوننت داد. این روش جالبی است که به دلیل نحوه برخورد React با JSX به وجود آمده است. دلیل کامل این روش را می‌توانید در مقاله Kent C. Dodds ببینید.همانطور که در ادامه می‌بینید، کامپوننت Counter رندر می‌شود، اما ExpensiveTree رندر نمی‌شود. دلیل این امر این است که رفرنس JSX که به عنوان prop به کامپوننت Counter داده شده است، با رندر قبلی یکسان است.استفاده از State Managementدر بعضی مواقع انتقال استیت به StateManagement و استفاده فقط در کامپوننتی که به آن نیاز دارد، میتواند راه حل خوبی به جای رندر کامپوننت پدر به همراه تمامی فرزندان باشد.دیدگاه شخصی خودم هنگام توسعهمن در هنگام توسعه، از memoization به عنوان آخرین راه حل استفاده می‌کنم. اگر نتوانستم راه‌حل مناسبی برای یک مشکل پیدا کنم، آنگاه از memoization استفاده می‌کنم. البته، در یک پترن تکراری خاص، استثناء، ترجیح من استفاده از memoization هست. نمونه کد زیر را در نظر بگیرید:این مورد را زیاد دیده‌ام. راه حل اولیه این است که مقدار ثابت را به initializer state بدهیم. این کار باعث می‌شود که مقدار در اولین رندر محاسبه شود و در رندرهای بعدی نیازی به محاسبه مجدد نباشد. اگر setState هیچ وقت صدا زده نشود و این مقدار فقط یک مقدار محاسباتی اولیه باشد، ترجیح من استفاده از useMemo است.مورد دیگری که زیاد رخ میدهد اینکه مقدار state شما به مقدار props وابسته باشد و مانند مورد زیر:می‌توان از useMemo برای بهبود کارایی این کد استفاده کرد. چرا؟ چون با تغییر props در کد بالا، دو بار رندر رخ می‌دهد. یک رندر به دلیل تغییر props است و رندر بعدی به دلیل تغییر مقدار state است.در کد زیر هوک های useState و useEffect حذف می شوند:پایانمن تلاش کردم تا تمام آنچه را که در مورد memoization می‌دانستم و طی چند سال تجربه کرده‌ام، در این مقاله بنویسم. برای این کار، از منابع مختلف نیز استفاده کردم. مطلب بالا خلاصه‌ای از تجربه خودم و مطالبی است که مطالعه کرده‌ام. ممنون می‌شوم نظرات شما را بشنوم و اگر جایی از مطلب نکته‌ای ایرادی وجود دارد، به من اطلاع دهید.منابعhttps://react.devhttps://overreacted.io/before-you-memo/https://kentcdodds.com/blog/optimize-react-re-rendershttps://tkdodo.eu/blog/the-uphill-battle-of-memoization</description>
                <category>حسین شیره جونی</category>
                <author>حسین شیره جونی</author>
                <pubDate>Fri, 02 Feb 2024 10:29:33 +0330</pubDate>
            </item>
                    <item>
                <title>بعد از نصب لینوکس ابونتو ۲۰.۰۴</title>
                <link>https://virgool.io/@shirejoni/%D8%A8%D8%B9%D8%AF-%D8%A7%D8%B2-%D9%86%D8%B5%D8%A8-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%D8%A7%D8%A8%D9%88%D9%86%D8%AA%D9%88-%DB%B2%DB%B0%DB%B0%DB%B4-aaqqpi7pffyp</link>
                <description>سلام دوستان من یک سالی هست که به صورت جدی در ابونتو فعالیت میکنم منظورم اینه که قبلا کار های اصلیم روی ویندوز بود و هر از گاهی به لینوکس سر میزدم. از سال پیش تصمیم گرفتم به صورت جدی ورود کنم به این قضیه و ابونتو رو یه بار دیگه نصب کردم و گفتم این یه سال باید به صورت جدی توی لینوکس فعالیت کنم اولش برام سنگین بود ولی هرچی بیشتر با لینوکس کار کردم و با محیط ور رفتم و کانفیگ های خودم رو انجام دادم خیلی بیشتر علاقه مند شدم تقریبا الان دیگه به جز کار با فتوشاپ به ویندوزم اصلا سر نمیزنم. خلاصه اینکه بعد از ۱ سال فعالیت جدی، تصمیم گرفتم کلا ویندوز رو بزارم کنار و از لینوکس استفاده کنم(قبلش هم کنار بود در اصل ولی خب روی سیستمم هر دو رو نصب داشتم و کندی سرعت داشتم). هر چند امروز دردسر های عجیبی در نصب ابونتو داشتم و نمی خوام در موردش صحبت کنم ولی در انتها بعد از بالا آمدن لینوکس تصمیم گرفتم لیست کار هایی که انجام میدم رو یه جایی بنویسم که برای دفعه بعدی داشته باشم و بعدش هم تصمیم گرفتم توی ویرگول بزارم شاید علاوه بر من به درد کسی بخوره البته شما هم میتونید پیشنهاد بدید که چه چیز هایی رو بهتره نصب کنم یا تغییر بدم ۱) مشکل لینوکس با cpu skylake و Realtek rtl8723be wirelessمدل لپتاب من ASUS X541U هست که از Realtek rtl8723be wireless استفاده میکنه و حالا به چه علتی نمیدونم ولی لینوکس با وایرلس این لپتاب مشکل داره و باعث میشه خطایی رو تولید کنه که بعد از یکی دوبار بالا اومدن لینوکس فضای خطای گراب پر میشه و باعث میشه سیستم بالا نیاد بعد از گشت و گذار های فراوان فهمیدم می تونم این مشکل به این صورت حل کنم با بروزرسانی فایل گراب درون:/etc/default/grub و تغییر خطGRUB_CMDLINE_LINUX_DEFAULT=&amp;quotquiet splash&amp;quot
// to
GRUB_CMDLINE_LINUX_DEFAULT=&amp;quotquiet splash pci=noaer&amp;quot و پس از ذخیره تغییرات دستور زیر را اجرا کنید:sudo update-grub۲) اجرای دستورات زیر برای اپدیت و بروزرسانی sudo apt update;
sudo apt upgrade;
۳) افزودن زبان فارس به کیبورداز اصلی ترین کار هایی که باید انجام بدیم اینه که زبان فارسی رو به کیبورد مون اضافه کنیم. طبق تصاویر می تونید جلو برید اگر ظاهر ابونتو من یکمی فرق میکنه نگران نباشید با من ادامه بدید خودتون دلیلش رو متوجه میشید :بر روی settings کلیک کنیدبه قسمت Region &amp; Language بروید و بر روی + کلیک کنیدبر روی سه نقطه(more) کلیک کنیدبه احتمال زیاد زبان Persian رو توی این لیستی که نشون میده پیدا نمیکنید و باید بر روی Other کلیک کنیدو حالا دنبال Persian بگردید و بر روی Persian کلیک کنید و دکمه Add رو بزنیدو حالا می توانید با دکمه ‍‍‍super + space زبان کیبورد خود رو عوض کنید۴) نصب کدک و یه سری ابزار های لازم که open-source نیستنداین پکیج شامل یه سری پکیج های تقریبا میشه گفت لازم هست(به خاطر کدک هاش میگم) که به خاطر دلایل copyright به صورت پیش فرض درون توزیع ابونتو نیست برای اطلاعات بیشتر می تونید به این صفحه مراجعه کنید.sudo apt-get install ubuntu-restricted-extras۴) نصب پکیج های git و curl و ...یه سری پکیج ها تقریبا بین هر توسعه دهنده ای ضرور هست و اینکه شما الان نصب کنی یه بعد از اینکه یه ابزاری را بخوای نصب کنی بفهمی لازم که اینا رو نصب کنی فرقی نمیکنه. البته من در کنازش synaptic هم نصب کردم اگه می خواید بدونید چی هست:نرم افزار Synaptic یک مدیریت برنامه برای لینوکس میباشد که دارای یک محیط گرافیکی کاربر  پسند میباشد که کار را برای کابران ساده میکند و با استفاده از آن  میتوانند نرم افزار های لینوکس را به راحتی نصب و یا به روز رسانی کنند. من بعضی موقع ها تو این محیط گرافیکی راحت تر یه پکیج رو پیدا میکنم برای حذف البته کم پیش میاد ولی  پیش میاد? sudo apt install curl make git build-essential synaptic۵) نصب zshاصلا بدون zsh نمیشه زندگی کرد?. zsh (زی شل z shell) یه شل سبک تر از bash هست و بهتون توصیه میکنم به همراه oh-my-zsh نصب کنید. oh-my-zsh این قابلیت رو فراهم میکنه که تم و اسکریپت و پلاگین های زیادی را رو zsh بالا بیارید و کار خودتون هنگام توسعه راحت کنید من نحوه نصب و پلاگین هایی رو که خودم نصب کردم را اینجا بهتون میگم.می تونید برای اطلاعات بیشتر و نحوه نصب و انواع روش های نصبش به این ریپازیتوری مراجعه کنیداگه git و curl رو تو مرحله ۴ نصب نکردید لازمه اینجا نصب کنید(اصلا این ترتیبا بی حکمت نیست).sudo apt install zsh &amp;&amp; sh -c &quot;$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)&quot;ممکنه همون اول که یه عکس از ترمینال من دیدید تعجب کنید که چرا دستوراتم رنگی هست باید بگم به خاطر نصب یکی از پلاگین های oh-my-zsh هست برای دیدن لیست کامل پلاگین های zsh می تونید به این لینک مراجعه کنید با کلیک کردن بر روی هر پلاگین اطلاعات اون پلاگین رو بخونید و اگه نیاز داشتید به oh-my-zsh اضافه کنید.من اینجا پلاگین هایی که خودم نصب کردم رو میزارم و یه توضیحاتی میدم درموردشون ولی شما می توانید تو اینترنت در مورد oh-my-zsh و zsh به فارسی و انگلیسی جستجو کنید و اطلاعات بیشتری بدست بیارید توی یوتیوب هم زیاد از این دست فیلم ها ریخته شده که اومدن zsh شون را کانفیگ کردند و پیشنهاد میکنم برید ببینید. نصب اکثر پلاگین ها راحت هست و باید فایل زیر را تغییر بدید و در قسمت پلاگین ها اسم پلاگینتون رو بنویسید و بعدش source کنید.~/.zshrcالف) پلاگین z: پلاگین کاربردی هست این پلاگین میاد لیست دایرکتوری هایی که رفتید رو تو حافظه اش نگهداری میکنه و مثلا دفعه بعد که ترمینال بازشد کافیه قسمتی از اسم اون دایرکتوری رو بنویسید و بعد از زدن تب ادرس کاملش رو قرار بده به عنوان نمونه:اسم یکی از پوشه های من هست که قسمتیش رو من نوشتمکه بعد از زدن تب آدرس کاملش رو به من نشون داد و بعد از enter به اون دایرکتوری منتقل شدم که میتونه توی سرعت جابه جایی تون در لینوکس کمک کنهب) پلاگین zsh-autosuggestions: این پلاگین میاد یه تاریخچه ای از دستوراتی که انجام دادید رو قرار میده و چون معمولا شما یه سری دستورات را زیاد میزنید می تونه بدردتون بخوره مثلا در تصویر زیر میبینید من یه قسمت از دستورم رو زدم و ادامه اش رو پیشنهاد داد که می تونید با زدن علامت جهت نما(به سمت راست &lt;-) کاملش کنیدچون نحوه نصبش یکمی فرق میکنه اینجا می نویسم ولی شما کامل لیست پلاگین ها رو بخونید و فایل کانفیگ مرا در انتها ببینید و بعد این دستورات را انجام بدید  البته راهنمای کاملش رو میتونید تو این ریپازیتوری پیدا کنید.‍‍‍git clone https://github.com/zsh-users/zsh-autosuggestions ${ZSH_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions
// put in your ~/.zshrc
plugins=(zsh-autosuggestions)ج) پلاگین sudo:بعضی موقع ها شما یه دستوری رو مینویسید و یادتون میاد که باید sudo قبلش قرار بدهید با اضافه کردن این پلاگین بعد از زدن دوبار esc خودش اول دستورتون تو ترمینال قرار میده به همین راحتی?.د) پلاگین docker:این پلاگین کمک میکنه موقع استفاده از docker یه autocomplete تمیزتر و بهتری را داشته باشید مانند شکل زیر:و) پلاگین zsh-syntax-highlighting:این پلاگین کمک میکنه دستوراتی که در ترمینال میزنید به صورت رنگی نمایش دهد و همچنین یه کمک فوق العاده ای که این قضیه داره اگه دستوری رو نشناسه قرمز نشون میده که سریعتر متوجه اون دستوری میشوید تا اینکه یه پیغام بعد از اجرای دستور تو لینوکس بنویسه که not recognized دمو این هم می تونید توی تصاویر های قبلی که فرستادم مشاهده کنید. جهت اطلاعات بیشتر و نحوه ی نصب به این لینک مراجعه کنید. در ادامه فایل کانفیگ خودم رو قرار میدم که هم یه reference باشه برای خودم و همچنین شما مشاهده کنید البته یه سری تغییرات نسبت به فایل پیش فرض وجود دارد که در ادامه این مقاله بعضی هاشون رو گفتم مثلا من اومدم alias برای zshconfig و zshsource  نوشتم که راحت تر باشم.export ZSH=&amp;quot/home/shirejoni/.oh-my-zsh&amp;quot
ZSH_THEME=&amp;quotrobbyrussell&amp;quot
plugins=(
git
z
zsh-autosuggestions
sudo
docker
)
source $ZSH/oh-my-zsh.sh
alias zshconfig=&amp;quotvim ~/.zshrc&amp;quot
alias zshsource=&amp;quotsource ~/.zshrc&amp;quot
export PATH=$PATH:/usr/local/go/bin
alias ls=&#039;lsd&#039;
alias l=&#039;ls -l&#039;
alias la=&#039;ls -a&#039;
alias lla=&#039;ls -la&#039;
alias lt=&#039;ls --tree&#039;
# fzf Configuration
source /usr/share/doc/fzf/examples/key-bindings.zsh
source /usr/share/doc/fzf/examples/completion.zsh
export FZF_DEFAULT_OPTS=&#039;--height 40% --layout=reverse --border&#039;
source /home/shirejoni/Programs/zsh-syntax-highlighting/zsh-syntax-highlighting.zshکه مشاهده میکنید من برای نصب پلاگین هایی که بالا معرفی کردم همه رو درون plugin قرار دادم البته  auto-suggestions یکمی فرق میکرد که اون بالا دستوراتش رو گفتم میزنید و درون plugins هم قرار میدید برای zsh-syntax-highlighting هم میتونید این دستورات زیر را انجام بدید:git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH_CUSOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting
echo &amp;quotsource ${(q-)PWD}/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh&amp;quot &gt;&gt; ${ZDOTDIR:-$HOME}/.zshrc۶) نصب vimاگه با ویم آشنایی ندارید به احتمال زیاد یه نگاه ما قبل تاریخ به این ادیتور دارید در حالی که اینجوری نیست و باید بگم همین الان اگه به ریپازیتوری vim یا neovim نگاه بندازید می فهمید که همین چند ساعت پیش یا نهایتا یک روز گذشته بروزرسانی شده و باید بگم ویم فوق العاده قوی هست و اون چیزی که فکر میکنید فرق میکنه و از اونجایی که من رو ابزار هایی که استفاده میکنم خیلی حساس هستم مطمئن باشید با دقت و بررسی کامل دارم این نظر رو میگم در ادامه متوجه میشید من حتی درون IDEA های Jetbrains هم از vimidea استفاده میکنم چرا که ویم در نوشتن فوق العاده سریعتر هست به خاطر شورت کات ها و امکاناتی که معرفی میکنه خلاصه سرتون رو درد نیارم یکمی در مورد ویم جستجو کنید یاد بگیرید تو یوتیوب ویدئو درموردش زیاد هست  و من اگه بخوام به جز نصب ویم، کانفیگ های ویم رو اینجا قرار بدم طول مقاله ۲ ۳ برابر میشه ترجیح میدم یه سری لینک بگم که ازشون برای کانفیگ استفاده کنید البته قبلش باید خود ویم رو یاد بگیرید، ویم نهایتا یه هفته طول میکشه ولی ارزشش رو داره.این دو تا چنل یوتیوب رو هم من پیشنهاد میکنم که هم آموزش vim میدهند و همچنین کانفیگ vim را انجام میدهند:۱ - کانال ChrisAtMachine۲- کانال ThePrimeagenبرای نصب ویم می تونید دستور زیر رو توی ترمینال بزنید البته من neovim رو ترجیح میدم که از همون اینترنت یا کانال هایی که بالا معرفی شد می تونید متوجه بشید چرا و چه تفاوت هایی دارندsudo apt install vim۶) نصب دیسکورددیسکورد یه برنامه کاربردی برای من هست و من تقریبا اکثر تماس هایی که میشه یا نیاز به screen share هست از این برنامه استفاده میکنم هر چند که چنل های خوب برنامه نویسی هم زیاد داره.می تونید از سایت دیسکورد فایل deb رو دانلود کنید و به این صورت نصب کنید. البته اسم فایل شما به احتمالا فرق میکنه.sudo dpkg -i discord-0.0.13.deb۷) نصب نرم افزار های فشرده سازی و extract کردن zip و rarدیگه لزوم این ابزار ها رو میدونیم و می تونید با استفاده از این دستور آنها رو نصب کنید:sudo apt install zip unzip rar unrar۸) نصب مدیا پلیر VLCمدیا پلیر vlc پر استفاده ترین مدیا پلیر لینوکس هست و اونم به نظر من خاطر پشتیبانی کاملی که از انواع فرمت های ویدیویی و صوتی دارد البته یه ویدیو پلیر خوب دیگه هم هست، به اسم Celluloid و برای کار باهاش بیشتر باید شورت کات هاش رو یاد بگیرید. چه خوب میشد گزینه های خوبی مثل PotPlayer یا KMPlayer برای لینوکس بودند. دلیلم هم به خاطر UI/UX بهتری که این ابزار ها دارند.sudo apt install vlc۹) نصب فونت شبنم | Shabnamفونت عالی و اپن سورس و رایگان شبنم، کار آقای صابر راستی کردار هست درسته که فونت وزیرشون محبوب تر هست ولی من این فونت رو خیلی دوست دارم و شما می تونید به این صفحه بروید و دیگر فونت های ایشون رو ببینید. ولی منم سعی میکنم در ادامه یه دموی از فونت هاشون را نشون بدم و بعد میرم سراغ نصب فونت شبنم.- فونت وزیرلینک صفحه فونت | لینک ریپازیتوری- فونت شبنملینک صفحه فونت | لینک ریپازیتوری- فونت ساحللینک صفحه فونت | لینک ریپازیتوری- فونت صمیملینک صفحه فونت | لینک ریپازیتوری- فونت گندملینک صفحه فونت | لینک ریپازیتوری- فونت پرستولینک صفحه فونت | لینک ریپازیتوری- فونت وزیر کدلینک صفحه فونت | لینک ریپازیتوری- فونت تنهالینک صفحه فونت | لینک ریپازیتوریبرای نصب فونت  شبنم می تونید فایل زیپش را از صفحه فونت، دریافت کنید و درون home تون در پوشه .fonts قرار بدید البته فراموش نکنید درون فایل منیجر پیش فرض ابونتو برای نمایش فایل های hidden باید ctrl + h رو زد و  فایل ها و دایرکتوری هایی که . اولشون هستند hidden هستند.یا می تونید به جایی که دانلود کردید بروید و این دستورات رو درون ترمینال اجرا کنید. ترجیحا همون روش بالا رو برید ولی خب گفتم دستورات رو هم بنویسم اینجا و سعی کردم یه راهی باشه که برای همه راحت باشه دستورات کاملا ساده هستند ولی یکمی زیادند نمی شد تو دو تا دستور بهتون بگم به خاطر اینکه می خواستم برای کسی مشکلی پیش نیاد این روش رو رفتم. دستورات به این شکل هستند که ابتدا یه پوشه میسازیم و اکسترکت میکنیم درون پوشه مانند تصویر mkdir shabnam-fontunzip shabnam-font-v5.0.1.zip -d shabnam-fontو حالا فونت های ttf رو درون یه پوشه جدا میریزیم که راحت باشیم برای انتقالشون:cd shabnam-font
mkdir ttf-shabnam
mv Shabnam-*.ttf ttf-shabnam
mv Shabnam.ttf ttf-shabnam
و حالا در اصل داریم فونت ها رو نصب میکنیم:mv ttf-shabnam/* ~/.fontsمی تونید برای cleanup هم این درستورات رو بزنید البته اگه درون پوشه shabnam-font هستید:cd ../
sudo rm -r shabnam-font
sudo rm shabnam-font-v5.0.1.zip۱۰) نصب tlp; برای افزایش طول عمر باطریمیگن طول عمر باطری رو افزایش میده ما که ندیدیم ولی نصب کردیم?:sudo add-apt-repository ppa:linrunner/tlp
sudo apt install tlp tlp-rdw
sudo tlp start۱۱) نصب دانلود منیجر XDMهیچی که از نظر من IDM نمیشه ولی خب اینم عملش خوبه ولی فقط UI خوبی نداره همین. می تونید از این لینک دانلود کنید و نحوه extract و نصبش هم به این گونه هست:tar -xvf xdm-setup-7.2.11.tar.xz
sudo ./install.shبرای استفاده بهتر از xdm، افزونه مرورگرش رو نصب کنید افزونه xdm برای فایرفاکسافزونه xdm برای کروم۲ دانلود منیجر دیگه هم اینجا اضافه میکنم دانلود منیجر های uGet و Persepolis که توسط آقایان navid shaghozahi و ALi rh معرفی شده اند و پیشنهاد میکنم حتما یه نگاهی به این ها بندازید و گزینه مطلوبتان را نصب کنید.- دانلود منیجر Persepolis: پرسپولیس یک دانلود منیجر و رابط کاربری گرافیکی برای Aria2 میباشد که با پایتون نوشته شده است. که opern source هست و قابلیت های خیلی خوبی دارد و برای اطلاعات بیشتر و نصب آن به این لینک مراجعه کنید- دانلود منیجر uGet: یک دانلود منیجر open source دیگر هست که از سال ۲۰۰۳ تا الان در حال توسعه هست و با c نوشته شده است. برای نصب و اطلاعات بیشتر میتونید به این لینک مراجعه کنید.۱۲) نصب Golangاز اون جایی که من به زبان golang علاقه مند هستم و قرار زبان اصلی من برای توسعه بشود اون رو نصب میکنم و خب نحوه نصبش رو نوشتم بهتون پیشنهاد میکنم به نگاهی به این زبان بندازید که واقعا Efficient و Productive هست. برای نصبش هم میتونید از این لینک استفاده کنید.بعد از دانلود از سایت golang می توانید دستورات زیر رو اجرا کنید.sudo tar -C /usr/local -xzf go1.15.6.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
go versionالبته من خط دوم رو همیشه درون .zshrc قرار میدهم که هنگام سورس شدن بتونم به go دسترسی داشته باشم.درون zshrc۱۳) نصب PHP و Apache و MySQLخب PHP اولین زبان سمت سروری هست که من کار کردم و هنوز هم ازش استفاده میکنم و زبانی هست که دوستش دارم و میدونم حالا حالا هست و کاربرد داره. من برای نصبش آپاچی رو نصب میکنم و مواقعی هم که nginx نیاز دارم اون رو با داکر میارم بالا اینجوری راحت هستم.sudo apt install apache2و mysql رو نصب میکنم از اونجایی که من قبلا نصب کردم و الان فرصت نصب دوباره رو ندارم که اسکرین بگیرم ترجیح میدم از این لینک به نصبش بپردازید بعد از نصب همونجور که در لینک هم هست دستور زیر رو اجرا کنید و پاسخ های مناسب رو بهش بدید البته من چون رو دسکتاپ هستم سعی کردم کار خودم راحت تر باشه و validation password رو غیر فعال کردم و موارد دیگه هم درون لینک توضیح داده شده استsudo mysql_secure_installationمن بعد از نصب از طریق sudo وارد mysql شدم و یه پسورد برای کاربر روت قرار دادم ببینید چون نسخه دسکتاپ هستیم این کار رو کردم تا راحت تر باشم در mysql-8 به صورت پیشفرض نمی تونید با پسورد وارد کاربر روت mysql بشد.ALTER USER &#039;root&#039;@&#039;localhost&#039; IDENTIFIED WITH mysql_native_password BY &#039;password&#039;;خب بعد از نصب MYSQL میریم سراغ نصب PHP، از اونجایی که PHP8 تازه release شده هنوز ریپازیتوری PHP7.4 رو نشون میده ولی توصیه مکنم PHP8 رو نصب کنید. دستورات زیر ابتدا ریپازیتوری PHP رو به ابونتو اضافه میکنه و بعد نصب میکنه نیاز به sudo apt update نیست چون در ابونتو ۱۹ به بعد خودش صداش میزنهsudo add-apt-repository ppa:ondrej/php
sudo apt install php8.0 php8.0-common php8.0-cli libapache2-mod-php8.0 -y
php -v # Show PHP version.
php -m # Show PHP modules loaded.? php8 یه سری module هم نیاز هست نصب کنید به صورت زیرsudo apt install php8.0-{bz2,curl,intl,mysql,gd,readline,xml}
sudo apt install php8.0-xdebug
من بعد از نصب php معمولا یه پوشه به اسم PHPProjects دارم که اونو رو دامین مجازی projects.test بالا میارم کارم رو راحت تر میکنه که نحوه انجامش هم به این صورت هست. که شما یه فایل درون ادرس زیر ایجاد میکنید و با ادیتور دلخواهتون باز کنیدو به صورت زیر کانفیگ کنید&lt;VirtualHost *:80&gt;
    ServerAdmin webmaster@localhost
    ServerName projects.test
    ServerAlias www.projects.test
    DocumentRoot /home/shirejoni/Projects/PHPProjects
&lt;Directory /home/shirejoni/Projects/PHPProjects&gt;
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
&lt;/Directory&gt;
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
&lt;/VirtualHost&gt;و حالا باید یکی از دستورات زیر رو به دلخواه بزنید بزنید تا یه نسخه لینک شده از فایلتون رو درون site-enabled قرار بدهدsudo a2ensite your_domain
یا
 ln -s /etc/apache2/sites-available/projects.test.conf /etc/apache2/sites-enabled/projects.test.confو بعد اش درون فایل /etc/hosts ادرس دامین مجازی رو قرار بدید و دستور زیر رو انجام دهید تا تغییرات اعمال شود sudo systemctl restart apache2.serviceدر دستورتی که مراحل رو به درستی انجام داده باشید و خطای syntax نداشته باشید باید به راحتی درون مرورگر بازکنید البته من لیستی از پروژه ها اینجا دارم ولی شما میتونید رو یه پروژه خاص دامین مجازی ایجاد کنید.این تغییر رو هم اعمال کنید درون آپاچی که فایل index.php رو به صورت پیش فرض قرار دهد. اون رو اول قرار بدید تا اولویت بیشتری داشته باشد.نصب phpmyadmin هم خیلی راحت هست کافی هست از این لینک دانلود کنید و درون پوشه ای که می خواد قرار بدید من درون همون پوشه PHPProjects قرار میدم که از طریق projects.test دسترسی داشته باشم.و طبق این لینک میتونید کانفیگ کنید البته از اون جایی که نسخه دسکتاپ هست و زیاد امنیتش مهم نیست من ترجیح دادم پسورد روت دیتابیسم رو مستقیم درون فایل بنویسم که راحت تر باشم به این صورت که شما فایل config.sample.inc.php  به config.inc.php تغییر میدهید یا کپی میکنید. و به این صورت  می نویسید: ۱۴) نصب Jetbrains IDEAبریم سراغ محبوب ترین IDEA من، یعنی Jetbrains تقریبا من هر چیزی رو میخوام شروع میکنم میریم میبینم براش jetbrains کد ادیتور(اینجا منظورم همون IDEA) نوشته یا نهنصب و کرک کردنشون یکیه و میتونید از سایت های پی سی دانلود (البته برای لینوکس نداره ولی کرکش رو من قبلا استفاده میکردم یکمی معمولا تاخیر داره تو انتشار ولی کرکش معتبر هست) و سافت 98 (برای لینوکس گذاشته و معمولا کرکاش کار میکنند) و دانلودلیدر ابتدا دانلود کنید و اکسترکت کنید حالا که XDM رو نصب دارید راحت تر هستید و میتونید سریعتر دانلود کنید. میتونید از محیط گرافیکی فایل منیجر برای این کار استفاده کنید ولی خب منم دستوراتش رو اینجا نشون دادمmkdir jetbrains-goland-idea
unzip JetBrains.GoLand.2020.3.0.Linux.zip -d jetbrains-goland-ideaبعد از extract کردن فایل های زیر خواهید دید که میتونید فایل goland-2020.3.tar.gz رو در محلی دلخواه extract کنید من بعدش انتقال دادم به پوشه ~/Programs که اگه بقیه فایل هایی که درون این پوشه هست رو نادیده بگیرید به این صورت هستو حالا میتونید طبق  ویديو و راهنمای این سایت های دانلود کرک کنید معمولا همه شون از کرک zhile استفاده میکنند و روش یکسانی دارند پس اگر توضیحات یکیشون رو متوجه نشدید به اون یکی سایت برید مثلا الان ویدیو تصویری براش درون soft98 هستحواستون باشه که کرک ها رو جدا دانلود کنید معمولا بروز می شوند البته اگر کرک تون کارنکرد از Terial Reset استفاده کنید که اونم میتونید یه تیک هست بزنید خودکار reset میکنه براتون و به همون راحتی کرک عمل میکنه(هرچند کرک کردن کار خوبی نیست ? ولی خودشون حق پرداخت رو من بستند منم کرک میکنم)می تونید PHPStorm رو هم به این صورت نصب کنید البته من این دو چون ابزار کارم هستند نصب میکنم شما میتونید به سایت Jetbrains برید ببینید چه محصولاتی رو برای چه زبان داره.من تقریبا IDEA رو  کاستومایز میکنم بر اساس نیاز خودم و سعی کردم شورت کات های این  IDEA یادبگیر ولی خب کاستومایز کردن و یادگیری اش با خودتون چون مبحث کاملا جدایی هست ولی خب تو اینترنت آموزش براش زیاد هست پلاگین هایی که نصب کردم رو اینجا میگممن از تم Gruvbox استفاده میکنم قبلش از Material Theme UI استفاده میکردم الان با gruv بیشتر حال میکنم. که هر دو اینها برای کد ادیتور های معروف افزونه دارند و می تونید استفاده کنید.خو شبختانه jetbrains تقریبا اکثر پلاگین ها و ابزار های مورد نیاز رو داره ولی خب من این سه پلاگین هم در کنارش نصب میکنماولی برای ایکون فولدر ها هست و دومی تم Grubbox Theme هست و در نهایت ideaVim که کمک می کنه ویم رو توی Jetbrains بیارید شما تا ویم رو نصب نکنید و کار نکنید باهاش نمیفهیمد چرا من این کار رو کردم وگرنه دلیلش رو متوجه میشید.اینم یه نمای کالی از PHPStorm که ظاهرش بعد از customize کردن به این شکل خواهد بودالبته من یه سری کانفیگ هم برای ~/.ideavimrc نوشتم برای پلاگین ideavim هست برای راحتی خودم هست هم اینجا مینویسم که برای خودم مرجع باشه و هم دوستانی که تجربه کار با ویم داشتند ممکنه بخواند تو جت برین ازش استفاده کنند ممکنه بدردشون بخوره.let mapleader=&amp;quot,&amp;quot
vnoremap &lt; &lt;gv
vnoremap &gt; &gt;gv
inoremap jk &lt;Esc&gt;
nnoremap &lt;silent&gt; &lt;C-s&gt; :w&lt;CR&gt;
nnoremap &lt;silent&gt; &lt;C-Q&gt; :wq!&lt;CR&gt;
nnoremap &lt;leader&gt;v :vsplit&lt;CR&gt;
nnoremap &lt;leader&gt;h :split&lt;CR&gt;
nnoremap &lt;leader&gt;q :close&lt;CR&gt;
nnoremap &lt;C-h&gt; &lt;C-w&gt;h
nnoremap &lt;C-j&gt; &lt;C-w&gt;j
nnoremap &lt;C-k&gt; &lt;C-w&gt;k
nnoremap &lt;C-l&gt; &lt;C-w&gt;l
nnoremap &lt;leader&gt;v &lt;C-W&gt;v
nnoremap &lt;leader&gt;h &lt;C-W&gt;h
vnoremap &lt;Tab&gt; &gt;gv
vnoremap &lt;S-Tab&gt; &lt;gv۱۵) نصب OBS Studioنرم افزار معروف برای recording و streaming هست الان که دوران کرونا هست و نمیدونم تو چه زمانی دارید میخونید این مقاله رو ولی خب من بعضی کلاس های درسی رو ضبط میکنم چون معمولا اهل جزوه نیستم و همین ویدیو ها را با سرعت زیاد گوش میدم البته کاربرد های دیگه ای هم برام داره. نصبش هم خیلی ساده هست. می تونید از طریق این لینک راهنمای نصبش رو ببینید.sudo apt install ffmpeg
# install obs studio
sudo add-apt-repository ppa:obsproject/obs-studio
sudo apt install obs-studio و در نهایت نصب شد: obs studio ۱۶) نصب Ankiنرم افزار Anki، یه نرم افزار عالی برای تثبیت اطلاعات در حافظه هست. من اگه جایی از کتابی، مقاله چیز جدیدی یاد بگیرم به انکی میفرستم تا حتما یادم بمونه اون مطلب. انکی یه نرم افزار که به صورت فلش کارت کار میکنه و از همون روش های معروف لایتنر استفاده میکنم. در وصفش همین بگم که خیلی از دانشجو های پزشکی برای حفظ مطالبشون از این نرم افزار استفاده میکنند و اینکه به ظاهر نرم افزار کاری نداشته باشید بر خلاف ظاهرش کاملا کاربردی هست و customizable و اینکه باید تو اینترنت سرچ کنید یه آموزشی در موردش ببینید تا راحت تر بتونید کار کنید باهاش برای نصبش از این لینک دانلود کنید.tar xjf Downloads/anki-2.1.37-linux.tar.bz2
cd anki-2.1.37-linux
sudo ./install.shو پلاگین های که من در anki استفاده میکنم زیاد نیست این دو تا هستند:افزونه Review Heatmapافزونه Syntax Highlighting for Code۱۷) نصب foxitreader یا okularمتاسفانه برای linux یه pdf reader با امکانات کامل و خوب نیست بلکه هر چی هست فقط نشون میدند امکانات درست حسابی که adobe یا foxitreader ویندوز ارائه میدهند، اینجا نیست و توی تحقیقات من شما می تونید از این دو نسخه استفاده کنید و خب حداقل بهتر از بقیه هستند. نصب Okular:sudo apt install okular نصب foxitreader:از سایتش نسخه لینوکس را دانلود میکنید و extract کنید و چون فایل run هست اجراش کنید مراحل نصب رو در پنجره باز شده ادامه بدید.tar xvf Downloads/FoxitReader.enu.setup.2.4.4.0911.x64.run.tar.gzو اجراش کنید.۱۸) نصب نرم افزار foliateبرخلاف PDF، یه نرم افزار باحال برای فرمت epub هست و امکانات خوبی داره پیشنهاد میکنم بهش یه نگاه بندازید، منی که فقط PDF می خوندم بعد از این نرم افزار و امکاناتش الان ترجیحم فرمت epub هست در صورتی که نبود PDF ?.sudo add-apt-repository ppa:apandada1/foliate
sudo apt install foliate۱۹) نصب Node و Yarnمن علاوه بر برنامه نویسی بکند، برنامه نویسی فرانت اند هم با React انجام میدم و نیاز دارم Node رو نصب داشته باشم البته شما ممکنه بک اند و فرانت روبا نود انجام بدید که فرقی نمیکنه.برای نصب نود می تونید بری توی این ریپازیتوری و نصب کنید و راهنمای کاملا واضحی داره:Node.js LTS:curl -sL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt-get install -y nodejsNode.js Current:curl -sL https://deb.nodesource.com/setup_current.x | sudo -E bash -
sudo apt-get install -y nodejsیارن هم مانند npm یه پکیج منیجر هست که نسبت به npm سریعتر و خروجی با پیغام های واضح تر و بهتری دارد.npm install -g yarn۲۰) نصب ترمینال Alacrittyترمینال Alacritty، سریعترین ترمینال موجود هست که تمرکزش بر روی سادگی و بهینه بودن هست ولی در عین حال Feature های خوبی داره و کانفیگ کردنش هم از طریق یه فایل yml هست.sudo apt install alacrittyو من یه کانفیگ ساده ای انجام دادم و یکمی تمش رو تغییر دادید و تم gruvbox را قرار دادم. که فایل کامنفیگ رو میتونید به صورت پیش فرض در این مسیر قرار بدید:~/.config/alacritty/alacritty.ymlکانفیگ نمونه که Alacritty قرار داده در این لینک هست و میتونید تغییر بدید. تغییرات من توی این لینک هست و بخاطر اینکه yml به space حساس هست و ویرگول درست نشون نمیداد توی یه gist قرار دادم. و خب ظاهر ترمینال رو که بالا دیدید نیاز به نمایش دوباره نیست.فقط من فونت Fira code رو نصب کردم به همراه icon های nerd font که میتونید از این لینک دریافت کنید. که مثل شبنم دانلود کنیدو درون پوشه .fonts قرار بدید چون تکراری هست انجام نمیدم اینجا.۲۱) نصب VMWareهمونجور که اون بالا گفتم من از ویندوز فقط فتوشاپش رو استفاده میکنم به خاطر همین تصمیم گرفتم از مجازی ساز استفاده کنم و با VMWare بالا بیاریم هر چند قبلش virtualbox رو امتحان کردم فایده نداشت vmware یه چیز دیگه است.برای نصب میتونید از این لینک دانلود کنید و extract کنید و درون terminal اجرش کنید و مثل مراحل نصب معمولی نرم افزار ها ادامه بدید.تصویری از VMWare۲۲) تنظیم فونت ایتااز جمله کار هایی که کردم این بود که فونت ایتا در لینوکس رو تغییر بدم  برای تغییر این فونت باید به این آدرس بروید و اسم فونت تون رو بنویسید من شبنم رو نوشتم. به این آدرس بروید.local/share/EitaaDesktop/edata/fc-custom-1.confو این فایل رو به این صورت قرار بدهید:&lt;?xml version=&#039;1.0&#039;?&gt;
&lt;!DOCTYPE fontconfig SYSTEM &#039;fonts.dtd&#039;&gt;
&lt;fontconfig&gt;
        &lt;match target=&amp;quotpattern&amp;quot&gt;
                &lt;test qual=&amp;quotany&amp;quot name=&amp;quotfamily&amp;quot&gt;
                        &lt;string&gt;Shabnam&lt;/string&gt;
                &lt;/test&gt;
                &lt;edit name=&amp;quotfamily&amp;quot mode=&amp;quotassign&amp;quot binding=&amp;quotsame&amp;quot&gt;
                        &lt;string&gt;Shabnam&lt;/string&gt;
                &lt;/edit&gt;
        &lt;/match&gt;
        &lt;dir&gt;~/.fonts&lt;/dir&gt;
&lt;/fontconfig&gt;و اینم تصویری از ایتا با فونت شبنم فقط جهت حفظ حریم شخصی دوستانم مجبور بودم پروفایل و اسمشون رو خط بکشم۲۳) تنظیم Theme:در مورد تم چون کمی طولانی میشد تصمیم گرفتم همون ویدیویی که دیدم رو بهتون معرفی کنم تا اگه شما هم خوشتون اومد انجام بدید این محیط ابونتو من هست:برای ایجاد همچین محیط هایی میتونید از این لینک هاکمک بگیرید:How To Make Ubuntu Look Like macOS Big SurHow to Make GNOME Desktop Look Like MacOS Big Surالبته من اون قدر هم کشته مرده مک نیستم? فقط چون این تم از نظر نسبت به بقیه تم ها قشنگ تر بود نصب کردم سلیقه ها فرق میکنه.۲۴) نصب VSCode:من قبلا برای ادیت یه فایل تکی از sublime استفاده میکردم ولی خب دیدم vscode هم بد نیست تصمیم گرفتم از vscode استفاده کنم ولی هنوز برای پروژه از Jetbrains استفاده میکنم و خب تجربه زیادی با vscode ندارم ترجیح میدم فقط نصبش رو بگم و دوستانی که تو این زمینه تخصص دارند کانفیگش رو بگند.می تونید از این لینک vscode را دانلود کنید و دستور زیر رو ترمینال بزنید تا نصب بشهsudo dpkg -i code_1.52.0-1607640828_amd64.debو اینم محیط VS Code من ولی میگم کانفیگ خاصی انجام ندادم و ترجیح میدم چیزی در این باره نگم تا کسی که بهتر با این ادیتور کار کرده توضیح بده اینجا یا تحت مقاله ای جداکه انشالله باب بشه و بقیه دوستان هم تجربیاتشون رو به اشتراک بگذارند.۲۵) نصب HTOP:برنامه خیلی خوبیه که تحت ترمینال بالا میاد که اطلاعات کلی در مورد پرسس ها و سیستم مانیتورینگ میده. یه جورایی نسخه ارتقا یافته top هست.اینم محیط htop:۲۶) افزونه های مرورگر فایرفاکس من:افزونه ی SaveFrom.net helper all-in-1: برای دانلود از یوتیوب هست البته از youtube-dl  هم استفاده میکنمافزونه BuiltWith: افزونه جامعی که اطلاعات کاملی از تکنولوژی صفحات میدهافزونه React Developer Tools: اگر توسعه دهنده React باشید این افزونه حتما بدردتون میخورهافزونه Speedup: این افزونه باعث افزایش سرعت ویدیو های صفحات وب می شود مثلا در یوتیوب محدودیت تا ۲ برابر هست ولی بعضی موقع ها بیشتر از این نیاز هستافزونه Abadis Persian: دیکشنری Abadis که از اون دیکشنری هاست که من قبولش دارم مخصوصا تو کلمات تخصصی بهتر از خیلی از دیکشنری ها عمل میکنه. این افزونه کمک میکنه یه جستجو معمولی داشته باشید برای اطلاعات بیشتر هم به سایت خودش میفرستهافزونه Simple Tab Groups: از اون افزونه های کاربردی هست من معمولا خیلی تب باز دارم و این کمک میکنه دسته بندی برای تب ها داشته باشم.افزونه NoScript Security Suite: معمولا اسکریپتی نباید اجرا بشه مگر اینکه خودم بخوام این رو معمولا دوست ندارید ولی من استفاده میکنم۲۷) Clean upالان خوبه یه clearn up هم انجام بدید?sudo apt autoremoveیه نکته ای هم که هست من برای اسکرین شات ها از اسکرین شات های خود ابونتو و همچنین از shutter استفاده میکنم:Ubuntu screenshots:shift + printscreen // بعد از اسکرین گرفتند درون فایل ذخیره میکنهctrl + shift + print screen // بعد از اسکرین گرفتند درون کلیپ بورد ذخیره میکنهshutter:محیط shuttersudo add-apt-repository -y ppa:linuxuprising/shutter
sudo apt install shutterبه پایان رسید این مقاله و هنوز ما اول راهیم?امیدوارم براتون مفید باشه من خودم تو دوران اولیه لینوکس خیلی به اینجور مقالات نیاز داشتم ولی خیلی پراکنده بود و اینجوری کامل و تحت یه مفهوم هیچ جا ندیدم خودم رو میگم و خب قرار بود یه جا یادداشت کنم reference باشه برام ولی تصمیم گرفتم به صورت مقاله در بیارم که اگه کسی هم خواست استفاده کنه بتونه. حتما نظراتتون رو اعلام کنید و دوستانی که تجربه دارند تو این زمینه در حدا امکان یه مقاله ای تو این زمینه بنویسند یا حداقل در نظرات بگند یا حداقل بگند من این مقاله رو کامل کنم ولی در کل تجربیاتتون رو به اشتراک بزارید ترجیحا یه مقاله کامل بنویسید خیلی خوب میشه لینکتون رو هم اینجا بزارید. خسته نباشید.</description>
                <category>حسین شیره جونی</category>
                <author>حسین شیره جونی</author>
                <pubDate>Sun, 20 Dec 2020 21:08:16 +0330</pubDate>
            </item>
                    <item>
                <title>راهنمای کامل useEffect در React</title>
                <link>https://virgool.io/@shirejoni/%D8%B1%D8%A7%D9%87%D9%86%D9%85%D8%A7%DB%8C-%DA%A9%D8%A7%D9%85%D9%84-useeffect-%D8%AF%D8%B1-react-jmvxttahnai3</link>
                <description>سلام از اولین پستی که در ویرگول گذاشتم دو سال گذشت و می خواستم مطالب بیشتری بنویسم ولی زمان فرصت نداد(بیشترش تنبلی خودم بود?) اما تلاش می کنم بیشتر فعال باشم ولی سعی کردم با یه پست خیلی عالی برگردم این مقاله بیان ترجمه شده از مقاله A Complete Guide to useEffect از Dan Abramov یکی از برنامه نویسای معروف React که مطالب عالی و خوبی در بلاگ شخصی اش می نویسد است.پیش نیاز مقاله آشنایی با React و همچنین انتظار میره تجربه کار با هوک ها را قبلا داشته باشید مقاله طولانی خواهد بود ولی به شما قول می دهم بعد از خواندن مقاله دید شما نسبت به useEffect و نحوه صحیح بکارگیری آن تغییر کند. شما در این مقاله دید عمیقی نسبت به این تابع پیدا خواهید کرد در انتها نظرتون رو در نحوه بیان من و کیفیت مقاله به اشتراک بگذارید. شما تعدادی کامپوننت با هوک نوشته اید حتی ممکنه اپلیکیشن کوچیکی باشه. و به احتمال زیاد راضی هستید و با کار با API راحت هستید و ممکن حتی یه سری Custom Hooks هم برای جلوگیری از تکرار نوشته باشید و به دوستانتون نشون داده باشید و اونا هم بگن:&quot;کارت عالیه&quot;اما بعضی موقع ها که از useEffect استفاده می کنید ممکنه کار نکنه! و تو دلتون بگید آیا من جایی اشتباهی انجام دادم، این که خیلی شبیه Class Lifecycles هست... اما آیا واقعا هست؟ ممکنه این سوالات را هم از خود بپرسید:چجوری می تونم از useEffect به جای componentDidMount استفاده کنم؟چجوری میشه  با استفاده از useEffect از API داده ها را بگیرم؟ اصلا [ ]، چی هست؟آیا می تونم از توابع برای وابستگی های effect استفاده کنم؟چرا بعضی موقع ها درون حلقه بی نهایت fetch کردن داده ها می افتم؟چرا بعضی موقع ها state و prop قدیمی را به من نشون میده؟وقتی که من استفاده از هوک ها را شروع کردم با همین سوالات موجه شدم!؟ حتی موقعی که داشتم راهنمای اولیه(initial docs) هوک را می نوشتم درک عمیقی از این نکات ریز و مهم نداشتم؟ این مقاله  به  سوالات بالا که ممکنه برای شما بدیهی باشه پاسخ میده.برای دیدن جواب سوالات، اول باید یه قدم به عقب برگردیم. قرار نیست این مقاله یه سری نکات را کنار هم بزار و سرسری بیاد نام ببره، قرار یه درک عمیقی از هوک useEffect به شما بده. در اصل شما چیز زیادی یاد نمیگیرید بلکه فراموش می کنید اشتباهاتی را که یادگرفتید!(چه جمله ی سنگینی!!!)توجه کنید که فقط زمانی که به useEffect در قالب class lifecycles نگاه نکنید همه چیز درست میشه.Unlearn what you have learned. — Yodaفراموش کن هرچی یاد گرفته ای. — یودا این مقاله واقعا طولانی هست و در اصل یک کتابچه است. فرمتی که من ترجیحش میدماگه راحت نیستید با این مقاله طولانی، به احتمال زیاد، شما باید منتطر بمونید تا جای دیگه ای درموردش توضیح داده بشه. مثل React که سال ۲۰۱۳ که اومد زمان برد تا برنامه نویسان طرز فکرشون رو تغییر بدن و یاد بگیرند و یاد بدهند.دوستان من توصیه می کنم حتما این مقاله را کامل بخونید چون واقعا نیازتون میشه و بدردتون خواهد خورد. — حسین شیره جونیهر رندری State و Props خودش را خواهد داشتقبل از اینکه بتونیم در مورد Effects صحبت کنیم باید درمورد Render بگیم.این یک شمارنده هست به خط هایلایت شده دقت کنید:خب این کد چه معنی میده؟ آیا count نگاه میکنه به state مون و یجوری خودش را اتوماتیک اپدیت می کنه؟ این نگاه ممکنه اول کار که داریم React را یاد میگیریم کمک کنه، اما مدل ذهنی دقیقی نیست.تو این مثال count یه عدد هست. داده ی عجیبی و غریبی مثل watcher, proxy و ... نیست. فقط یه عدد نقلی خیلی قشنگ مثل این:اولین بار که کامپوننت مون رندر میشه، متغییر count که از useState(0)، میگیریم مقدارش صفر هست. وقتی که setCount(1)، را صدا میزنیم، React کامپنوننتمون دوباره صدا میزنه، اما اینبار مقدار count، یک خواهد بود و ... .هر بار که state مون اپدیت می کنیم، React کامپوننت ما را صدا میزنه و هر رندری counter را برابر با مقدار ثابت از state خودش میبینه. یعنی counter یه متغییر ثابت درون تابع خواهد بود که مقدارش برابر با state value اون رندر(اوکی:-\)پس این خط هیچ کار ویژه ای برای Data Binding انجام نمیده:کاری که میکنه اینه که یه مقداری عدد را درون خروجی رندر میزاره. این مقدار عددی، توسط React فراهم میشه. یعنی وقتی setCount، صدا زده میشه، React کامپوننتمون با مقدار جدید برای count، صدا میزنه. سپس React محتوای DOM را بروزرسانی میکنه تا با نتیجه آخرین رندرمون هم خوانی داشته باشه.نکته ای که هست اینه که مقدار count، در هر رندری در طول زمان تغییر نمی کنه. بلکه این کامپوننت ما هست که دوباره صدا زده می شود؛ و در هر رندری مقدار count خودش را میبینه و این count مربوط به خودش هست نه رندر دیگه ای.هر رندری Event Handler خودش را خواهد داشتتا کنون خوب بود. حالا در مورد Event Handler قضیه چی میشه؟به این مثال نگاه کن. این مقدار count را با پیغام alert بعد از ۳ ثانیه نشون میده.خب بیایید بگیم که من این کار ها را میکنم:مقدار count را تا سه افزایش میدم(با کلیک روی &quot;Click me&quot;)روی دکمه &quot;show alert&quot; کلیک می کنمقبل از اینکه ۳ ثانیه تموم بشه مقدار count را به ۵ افزایش میدمانتظار دارید پیغام alert چه عددی را به شما نشون بده؟ آیا ۵ رو که مقدار state شمارنده مون خواهد بود، نشون میده؟ یا عدد ۳ را که وقتی روی دکمه کلیک شد مقدار state مون بود، نشون میده؟بهتره خودتون امتحان کنید.پیغام alert، مقدار ۳ را نشون خواهد داد همان مقداری را که وقتی کلیک شد برای خودش در نظر گرفت.(روش های مختلفی نیز وجود دارد که عدد های دیگه ای را نشان دهد، اما تمرکز ما روی همین رفتار پیش فرض خواهد بود. و موقعی که داریم یه مدل ذهنی می سازیم، خیلی مهم که تشخیص بدیم از مسیر یادگیری با مقاومت کمتر استفاده کنیم تا به نتیجه مطلوب برسیم.)اما چگونه این کار میکند؟ما صحبت کردیم که مقدار count، یه مقدار ثابت هست در هر رندری که ما تابع مون را صدا میزنیم هست. تابع ما چندین بار صدا زده می شود(در هر رندر یکبار)، در هر کدام از این زمان ها، count داخل تابع ثابت و برابر با یه مقداری خاصی هست (state برای همون رندر).این فقط به React مربوط نمیشه یا خاص React نیست. توابع معمولی هم همین جوری انجام میشند:در این مثال، مقدار someone چندین بار تغییر میکند.(دقیقا مثل زمان هایی در React، که state کامپوننت مون تغییر کنه) اما داخل sayHi، یه متغییر محلی name وجود داره که مربوط به person زمان صدا زدن(call) خودش خواهد بود. این مقدار ثابت، محلی خواهد بود(لوکال) و در نتیجه وقتی که timeout تمام می شود، هر پیغام alert، مقدار name مربوط به خودش را خواهد داشت.این کد پایین به ما توضیح میده چجوری event handler مون مقدار count مربوط به زمان کلیک شدن را میگیره. اگر همین قاعده را برای اینجا قائل شویم متوجه میشیم که هر رندر مقدار count خودش را می بینه:بنابرین میشه نتیجه گرفت، هر رندری ورژن خودش را از handlerAlertClick خواهد داشت. هر کدوم از این ورژن ها مقدار count خودش را خواهد داشت:این دلیل اینه که چرا هر event handlers مربوط به رندر خاصی خواهد بود، و شما کلیک می کنید، تلاش می کنه تا counter مربوط به همان رندر را بخواند.در هر رندری، props و state  برای همیشه ثابت خواهد ماند. بنابرین هر چیزی که داره از این مقادیر استفاده می کنه مربوط به همون رندر خواهد بود و حتی توابع async هم همان مقدار را خواهند دید.هر رندری effect خودش را خواهد داشتقرار بود که این پست درمورد effect ها صحبت کند اما تا الان چیزی در موردش نگفتیم. اینو بدونید که واقعا effect هم فرقی با بقیه نمی کند و همین قوانین را خواهد داشت.بهتره یه مثال بزنیم:این جا یه سوال از شما می پرسم: چگونه effect آخرین مقدار count را خواهد خواند؟ممکنه یه کد پیچیده ی  عجیب و غریبی باشه که مقدار count را چک میکنه و درون تابع effect قرار میده؟ ممکنه مقدار count، از نوع Mutable باشه بنابرین کامپوننت ما همیشه آخرین مقدار count را خواهد دید؟ نخیر!ما تا الان دیگه فهمیدیم که مقدار count، یه مقدار ثابت مربوط به آن رندر می باشد. event handler مقدار count مربوط به رندری که درونش اصدا زده میشوند خواهد دید. چون count یه متغییر هست درون scope که دسترسی دارند بهش. این قاعده برای useEffect هم درست است.مسئله این نیست که count چجوری داخل محیط ثابت تغییر می کند. بلکه خود تابع effect هست که در هر رندر تغییر می کند.هر نسخه از رندر، مقدار count مربوط به آن را خواهد دید:کامپوننت React، تابع Effect را که نوشتی بعد از رها کردن(flushing) تغییرات به DOM(ایجد تغییر ات در DOM) و اجازه به مرورگر برای تغییر در صفحه، اجرا میکند.بنابراین حتی اگه در مورد تابعی که کلا یک کار انجام میده(مثل تغییر عنوان document) صحبت کنیم، این تغییرات در هر رندر، توسط تابع Effect آن رندر انجام خواهد شد و هر کدام از این توابع state و props مربوط به رندری که درونش هست را خواهد دید.به صورت کلی، میشه گفت که توابع Effect یه بخشی از رندر هستندبازم میگم، توابع Effect مربوط به همان رندر خواهند شد دقیقا مثل Event Handlers.برای اینکه مطمئن شیم که فهمیدیم و کامل درکش کردیم بهتره اولین رندری که انجام میشه را یه نگاهی بندازیم:فریم ورک React: رابط کاربری(UI) که وقتی state صفر هست را بده.کامپوننت ما: بفرما این نتیجه رندر من خواهد بود:&lt;p&gt;You clicked 0 times&lt;/p&gt; همچنین یادت باشه بعد از اینکه کارت رو انجام دادی این Effect را اجرا کنی:() =&gt; { document.title = &#x27;You clicked 0 times&#x27; }فریم ورک React: باشه چشم، دارم UI را اپدیت میکنم. مرورگر، یه سری چیز به DOM اضافه کردم.مرورگر: اوکی، الان صفحه را تغییر میدم.فریم ورک React: خب الان میرم سراغ اجرای Effect که به من دادی.اجرا: () =&gt; { document.title = &#x27;You clicked 0 times&#x27; } .خب بیایید ببینیم چه اتفاقی می افته اگر کلیک کنیم:کامپوننت ما: هی React، مقدار state را به یک تغییر بده.فریم ورک React: رابط کاربری(UI) که وقتی state یک هست را بده.کامپوننت ما: بفرما این نتیجه رندر من خواهد بود:&lt;p&gt;You clicked 1 times&lt;/p&gt; همچنین یادت باشه بعد از اینکه کارت رو انجام دادی این Effect را اجرا کنی:() =&gt; { document.title = &#x27;You clicked 1 times&#x27; }فریم ورک React: باشه چشم، دارم UI را اپدیت میکنم. مرورگر، من DOM را تغییر دادم.مرورگر: اوکی، الان تغییرات جدید صفحه را انجام میدم.فریم ورک React: خب الان میرم سراغ اجرای Effect که مربوط میشه به رندری که انجام دادم.اجرا: () =&gt; { document.title = &#x27;You clicked 1 times&#x27; } .هر رندری، هر چیز مربوط به خودش را خواهد داشتخب تا الان ما فهمیدیم که هر Effect، اجرا میشه بعد از رندر و خودش جزء ی از خروجی کامپوننت مون هست و props و state مربوط به رندر خودش را می بیند.بیایید یه امتحانی انجام بدیم، این کد را در نظر بگیرید:من چند بار پشت سر هم کلیک میکنم، نتیجه که لاگ میشه را حدس بزنید؟یه چند خط لاگ میبینیم که هر کدام مربوط به یه رندر خاصی می باشند و count خودشان راخواهند داشت می تونید اینجا چک کنیدممکنه شما بگید: که این جواب بدیهیه و آیا انتظار نتیجه دیگه ای داری؟خب، بهتره بگم این مورد در مورد this.state که توی کلاس با هاش کار میکنیم. اینجوری نیست و خیلی راحت ممکنه به اشتباه فکر کنیم که این روش معادلش کد ریز هست:چون این کد یعنی this.state.count همیشه به آخرین count مان اشاره میکند نه مربوط به آن رندر که صدا زده می شود، بنابراین شما عدد ۵ را چندین بار می بینید.من فکر می کنم Hooks بر اساس کلوژر در جااواسکریپت عمل میکنه در حالی که روشی که در کلاس بکار بردیم از یه باگ منقضی شده در کلوژر رنج می بره. و این بخاطر اینه که React اشاره می کنه به this.state Mutate در کلاس که همیشه به آخرین تغییرات اشاره میکنه.کلوژر برای زمان هایی مناسب هست که متغییر های ثابتی داشته باشیم چون کمک می کنه براحتی در موردش فکر کنیم چون مقادیر ثابت خواهند بود. و همونجوری که صحبت کردیم prop و state هرگز تغییر نمی کنه در یک رندر خاص. در مورد کلاس ها هم می تونیم مشکلشون رو با همین کلوژر ها حل کنیم.شنا کردن برعکس جهت جریان رود خانهیه این دو مثال اگه دقت کنید مشاهده می کنید باهم برابراند:در داخل کامپوننت در زمان یک رندر، این مهم نیست که شما مقایر را از state یا props می خونید چون ان ها تغییری نمی کند.البته ممکنه، بعضی مواقع شما بخواهید به آخرین مقدار متغییر در داخل callback که درون Effect استفاده می کنید دسترسی پیدا کنیم، که یکی از آسون ترین روش ها استفاده از refs است. که در این مقاله درموردش توضیح داده شده است.توجه کنید که وقتی می خواهید به جدید ترین مقداری از متغییر که در داخل رندر های گذشته است دسترسی پیدا کنید دارید برخلاف جهت جریان شنا می کنید. این اشتباه نیست(حتی بعضی مواقع ضروری هست) اما استفاده از این روش که خلاف جهت جریان کدتون هست باعث کثیف شدن کدتون خواهد شد.این یه نسخه از کدمون هست که روشی مشابه روش کلاس(دیدن آخرین تغییرات) را خواهد داشت:حالا درمورد Cleanup چی؟بعضی از افکت ها (effect) ممکنه مشکل Cleanup داشته باشند. مخصصوصا مواقعی که هدف اندو کردن(undo)  یه effect برای مواردی مثل سابسکرایب(subscribe) باشد.اگه بیایم props را برای رندر اول {id: 10} در نظر بگیریم و برای رندر دوم {id: 20} . شما ممکنه فکر کنید چنین اتفاقاتی خواهد افتاد.فریم ورک React افکت(effect) شما را برای {id: 10} تمیز می کند.(Clean Up)فریم ورک React کامپوننت شما را برای {id: 20} رندر می کند. فریم ورک React افکت (effect) شما را برای {id: 20} اجرا می کند.این تقریبا اون چیزی نیست که اتفاق می افتد.با این مدل ذهنی که شما فرض کردید، شما ممکنه فکر کنید که Cleanup مقدار قدیمی props یعنی {id: 10} را خواهد دید و قبل از رندر مجدد اجرا خواهد شد. و سپس effect جدید مقدار جدید props را یعنی {id: 20} خواهد دید چونکه بعد از رندر اجرا خواهد شد. این دقیقا مدل ذهنی هست که بخاطر class life cycles برای شما به وجود آمده است. و دقیقا چیزی نیست که اتفاق می افتد. بزارید یه نگاهی بندازیم.فریم ورک React توابع Effect را فقط بعد از اینکه مرورگر تغییرات صفحه را اعمال کرد، اجرا خواهد شد. این کمک می کنه که برنامه شما سریعتر اجرا شود و نیاز نداشته باشد که تغییرات صفحه را بلاک کند. Cleanup توابع Effects هم با کمی تاخیر انجام می شوند. Cleanup تابع Effect قبلی بعد از رندر مجدد کامپوننت اجرا خواهد شد.فریم ورک React کامپوننت شما را برای {id: 20} رندر می کند. مرورگر تغییرات صفحه را انجام میدهد در نتیجه ما UI برای {id: 20} را خواهیم دید.فریم ورک React افکت(effect) شما را برای {id: 10} تمیز می کند.(Clean Up)فریم ورک React افکت (effect) شما را برای {id: 20} اجرا می کند.شما ممکنه تعجب کنید: که چگونه ممکنه تابع cleanup افکت قبلی هنوز بتونه مقدار قبلی props یعنی را {id: 10} ببینه بعد از اینکه به {id: 20} تغییر کرده است؟فکر کنم ما قبلا اینجا بودیم نه ...?این نقل قول از پاراگراف های قبلی هست:هر تابعی در داخل کامپوننت ما(شامل Event Handlers, effects, timeout و API ها) مقدار props و state رندری را که در ان تعریف شده بود میگره.خب جواب الان واضح است، تابع Cleanup افکت اخرین مقدار props را نخواهد دید. بلکه مقدار props که در ان رندر تعریف شده است را خواهد خواند.این همون کاری هست که React با افکت ها انجام می دهد. و برنامه را سریعتر خواهد کرد و مقادیر قدیمی ازبین نخواهند رفت اگر کد ما به اون ها نیاز داشته باشد.همگام سازی، چرخه زندگی نیستیکی از محبوب ترین ویژگی های React برای من اینه که رندری اولیه و رندر ها تغییرات را یکی کرده است. و ورودی برنامه را کاهش داده است.الان کامپوننت مون را اینگونه در نظر بگیرید:این فرقی نمی کنه که کامپوننت ما ابتدا این &lt;Greeting name=&quot;Dan&quot; /&gt; باشد و بعد به این &lt;Greeting name=&quot;Yuzhi&quot; /&gt; تبدیل شود یا اینکه کلا از اول این &lt;Greeting name=&quot;Yuzhi&quot; /&gt; باشد. در نهایت ما “Hello, Yuzhi” را خواهید دید.مردم میگند: سفر کردن مهمه، نه مقصد. اما در React، این قضیه برعکس هست. همه چیز مقصد هست و نه خود سفر. این تفاوت، مثل صدا کردن توابع $.addClass  و $.removeClass  در کتابخانه jQuery(سفرمان) و مشخص کردن این که چه کلاسی باید درون کد React باشد.(مقصدمان)فریم ورک React، محتوای DOM را با استفاده از props و states فعلی همگام سازی میکند. در موقع رندر کردن هیچ تفاوتی بین mount و update نیست.درمورد افکت ها هم باید همین گونه فکرکنید. useEffect به شما کمک میکنه بر اساس states و props مان، خارج از درخت React، محتوایمان را همگام سازی کنیم.این نحوه رفتار افکت ها با مدل mount/update/unmount کاملا متفاوت هست. و بهتر  است متوجه این موضوع بشوید و با آن کنار بیاید. اگه شما افکتی می نویسی که که رفتار متفاوتی را بر اساس اینکه آیا دفعه اول هست که رندر می شود یا خیر، کاملا دارید برخلاف جریان رود، شنا میکنید. ما در همگام سازی شکست می خوریم اگر به سفر اهمیت بدهیم نه مقصد.به React یاد بده که تفاوت های effects را بشناسه!ما از قبل یاد گرفته ایم که React تنها بخشی از DOM که نیاز به بروزرسانی دارد را تغییر میدهد.وقتی که شما بروزرسانی میکنید از:به:فریم ورک، دوتا ابجکت را مشاهده میکنه:با نگاه کردن به ابجکت ها، متوجه میشه که مقدار خصوصیت  children تغییر کرده و نیاز داره که DOM اپدیت بشه، اما مقدار خصوصیت className تغییر نکرده، بنابراین می تونه به این صورت انجام بده:آیا می تونیم با effects هم همین کار بکنیم؟ خیلی خوب میشه اگه اجراشون کنیم وقتی که نیاز هست افکت تاثیر داده بشه و نه بیشتر.برای مثال، ممکن کامپوننت ما دوباره رندر شود بخاطر اینکه state مون تغییر کرده:اما افکت ما از counter استفاده نمی کنه. افکت ما عنوان سند را document.title با مقدار name که از props میگیره، همگام سازی میکنه، اما در رندر مجدد که این مقدار یکسان هست، همگام سازی مجدد document.title در هر بار که مقدار counter تغییر میکنه، به نظر خوب نمیاد. باشه، اما آیا React، متوجه تفاوت effect هامون میشه؟نه نمی تواند، React نمی تونه متوجه یکسان بودن افکت هامون بشه تا موقعی که صداشون نکرده.این دلیلی هست برای اینکه اگه بخوای از اجرای مجدد غیر ضروری افکت ها جلوگیری کنید، باید از آرایه های وابستگی(که بهشون میگیم وابستگی از این به بعد) به عنوان آرگومان دوم در تابع useEffect استفاده کنید.الان کد بالا مثل این میمونه که به React بگیم: هی ری اکت، میدونم که نمی تونی داخل تابع را ببینی چی هست اما به جون خودم، فقط داره از name استفاده میکنه و چیز دیگه ای از اسکوپ رندر، درون خود استفاده نمی کنه.بنابراین اگر تمامی ایتم های آرایه وابستگی که برای این افکت نوشته ای با مقادیر قبلی که در رندر قبلی برای افکت فرستادیم یکسان بود. React، این افکت را اجرا نمی کنه و نادیده میگیرد:اما اگه حتی یکی از این ایتم های آرایه یکسان نبود، React نمی تونه این افکت را نادیده بگیره و اجراش میکنه.به React، در مورد وابستگی ها دروغ نگو!دروغ گفتن به React، درمود وابستگی ها عواقب بدی خواهد داشت.(یاد این جمله افتادم: هر گونه کپی بدون اجازه صاحب اثر، پیگر قانونی خواهد داشت.:-) ). کاملا واضح هست، اما من خیلی دیدم که برنامه نویسانی،  با مدل ذهنی که هنوز از کلاس دارند، با useEffect کار می کنند سعی می کنند این قوانین را دور بزنند.(اوایل من خودم هم انجام میدادم)بخش سوالات متداول هوک در سایت React در مورد جایگزین های این کار توضیح داده البته ما هم پایین تر درموردش صحبت میکنیمشما قطعا میگید: اما من می خوام فقط برای بار اول(mount) انجام بشه. فعلا، اینو یادت باشه: اگه وابستگی مشخص کردی، باید تمام متغییر هایی که درون کامپوننت هستند و داری درون افکت استفاده میکنی رو اونجا بنویسی. اما بعضی مواقع که این کار را انجام میدید، براتون مشکل ایجاد میکنه. برای مثال ممکن درون یه حلقه بی نهایت Fetch Data یا دوباره ساختن بیش از حد کانکشن ساکت(socket) گیر کنید، اما راه حل حذف کردن وابستگی ها نیست. ما درموردش صحبت خواهیم کرد.چه اتفاقی میفته وقتی به وابستگی اشتباه بگیماگه وابستگی به درستی مشخص کنه تمام مقادیر که درون افکت استفاده میکنید را، اون وقتی React متوجه میشه که باید دوباره افکت را اجرا کنه:مقادیر وابستگی تغییر کرده اند در نتیجه افکت را دوباره اجرا میکنیماما اگه ما برای این افکت وابستگی خالی را []، یعنی هیچ وابستگی نداشته باشه، مشخص کنیم:در این مورد ممکنه مشکل کاملا واضح باشد، اما توجه بهش می تونه شما را از نادیده گرفتن این مسئله در مورد های مشابه باز دارد.برای مثال، اگه بخواهیم یک شمارنده بسازیم که هر ثانیه بشمارد. با مدل ذهنی کلاس می تونیم اینجوری پیاده سازی کنیم: فقط یکبار interval بساز، اخر کار هم ازبین ببرش. این جا راه حل این مسئله با استفاده از Class کامپوننت پیاده سازی شده است. اگر بخواهیم همین را به useEffect تبدیل کنیم، ما از روی عادت وابستگی را [] در نظر میگیریم. &quot;من می خواهم یکبار اجرا شود&quot;:اما این شمارنده تنها یکبار اجرا می شود.اگه مدل ذهنی شما این باشه که وابستگی مشخص میکنه که باید افکت اجرا شود، این مشکل ممکنه برای شما بحران به وجود آورد. شما می خواهید افکت یکبار اجرا شود چون که یک نوع interval دارید، خب پس چرا این مشکل به وجود می آید؟الان کاملا برای شما واضح است که وابستگی ها زبانی برای صحبت کردن با React، درمورد تمام چیز هایی هست که افکت درون خود از اسکوپ رندر استفاده میکند. افکت داره از count استفاده می کنه اما شما به دروغ گفته اید [] از هیچ چیزی استفاده نمیکند. الان که متوجه میشید که چرا نباید دروغ بگید.در رندر اول count برابر ۰ است.بنابراین، setCount(count + 1) در اجرای افکت پس از رندر اولیه معادل setCount(0 + 1)  است. بنابراین چون ما هیچ موقع دیگه افکت را صدا نمی زنیم بخاطر نبود وابستگی، در هر ثانیه افکت ما برابر این setCount(0 + 1) خواهد بود.ما به React، دروغ گفته ایم که افکت ما به هیچ یک از متغییر های کامپوننت مان وابسته نیست. درحالی که هست.افکت ما داره از count استفاده میکنه، متغییری که درون کامپوننت هست و بیرون از تابع افکت ما.بنابرین مشخص نکردن وابستگی و استفاده از []، باعث ایجاد باگ درون برنامه React ما می شود. React وابستگی هامون رو مقایسه میکنه و متوجه میشه که باید از اجرای مجدد این افکت صرف نظر کند.متوجه مشکلاتی شبیه این شدند، سخت هست. بنابراین من پیشنهاد میدم که مشخص کردن وابستگی ها را یک قانون برای خودتون قرار بدید. و همیشه همه این وابستگی ها را مشخص کنید.(ما یک ابزاری ساختیم اگه بخواهی مجبور کنید تیمتون رو به رعایت این موضوع، کمکتون میکنه)دو راه برای اینکه در مورد وابستگی ها صادق باشیمدو راه برای اینکه درمورد وابستگی ها صادق باشیم وجود دارد شما باید راه حل اولی را انتخاب کنید و بعد راه حل دوم را اگر نیاز شد.راه حل اول، تمامی وابستگی ها را مشخص کنید، که شامل تمامی متغییر هایی از کاپوننت مان می شود که درون افکت استفاده میکنیم. بزارید count به عنوان وابستگی قرار بدیم.این باعث میشه وابستگی ها مون به درستی مشخص بشه، ممکنه ایده آل نباشه اما اولین کاری هست که باید با این مشکل انجام بدهیم. حالا یه تغییر توی count  باعث اجرای مجدد افکت مان خواهد شد، که در هر بار interval درون رندرمان،به مقدار حال حاضر count  ارجاع می دهد setCount(count + 1):این مشکل مون رو حل می کنه اما در هر بار رندر که مقدار count تغییر میکند، interval مان پاک می شود و دوباره ساخته می شود. که ممکنه خوش آیند نیاید:راه حل دوم اینه که کد درون تابع افکت مان را تغییر بدهیم که بیشتر اون چیزی که بخواهیم بهش احتیاجی نباشد یعنی وابستگی نداشته باشد. ما نمی خواهیم در مورد وابستگی دروغ بگویم بلکه می خواهیم افکت مان را تغییر بدهیم که وابستگی تعداد کمتری از متغییر های داخلی کامپوننت داشته باشد.بزارید یه نگاه کنیم به راه حل هایی برای حذف وابستگی در افکت مان.افکت مان را بی نیاز کنیمما می خواهیم از شر وابستگی به count خلاصه شویم.برای این کار ما باید از خودمون بپرسیم اصلا count برای چه می خواهیم؟ اگه فقط برای استفاده درون setCount بخواهیم که می تونیم از  فرم Functional که از state قدیم مون هم استفاده میکنه استفاده کنیم:با این setCount(c =&gt; c + 1) دقیقا مشخص میکنید که چجوری state مون باید تغییر کنه. البته کاربرد های دیگه ای هم داره مثلا وقتی بخواهید چند بخش از state مون را اپدیت کنیم.توجه کنید که ما هیچ تقلبی نکردیم و به صورت کاملا درست وابستگی را حذف کردیم، و تابع افکت مان هیچ موقع مقدار counter  از درون اسکوپ رندرمان نخواهد خواند.شما می تونید خودتون انجام بدید اینجا.بروزرسانی فانکشنال و Google Docsیکی از کار هایی که در همگام سازی انجام میدهیم، آگاه سازی و بروزرسانی سیستم مان از تغییراتی که در state الان مان هست. برای مثال، ویرایش یک سند Google Docs هیچ موقع کل صفحه برای سرور ارسال نمی شود. این خیلی هزینه بر خواهد بود. اما می توان به سرور کار هایی که کاربر می خواهد انجام دهد ارسال کرد.در حالی که مورد مثال مان کاملا متفاوت هست، اما از یه قاعده پیروی میکند. این کمک میکنه تا حد امکان کمترین اطلاعاتی که لازم هست را از افکت به کامپوننت ارسال کنیم. بروزرسانی به صورت Functional Form مانند setCount(c =&gt; c + 1) اطلاعات کمتری را نسبت به setCount(count + 1) منتقل می کند. چرا که تحت شعاع مقدار فعلی count نیست و فقط یک action هست.فکر کردن به سبک React شامل قانون پیدا سازی کمترین تعداد state هم می شود. این هم همان قانون هست اما برای اپدیت.انکود کار هایی که کاربر کرده و ارسال آن به گوگل داکس در موقع ویراش سند درحالی که روش کشش آوری هم هست. Functional Updated هم همین نقش را در React دارد.اما استفاده از setCount(c =&gt; c + 1)  محدود هست. چون اگر بخواهیم یک state بر اساس state دیگری تغییر کند نمی تواند به ما کمک کند البته یه خواهر بزرگتری هم دارد که می توان از آن استفاده کردuseReducer.جدا سازی اکشن بروزرسانیمانبزارید مثال قبلی را تغییر بدهیم استفاده کینم از دو تا state درون کامپوننت مان count  و step. تابع interval مان مقدار count  را بر اساس step زیاد می کند.دقت کنید که ما کدمان را دور نمی زنیم چون از step استفاده کردیم پس در وابستگی مان مشخص میکنیم و کد مان به درستی اجرا می شود.این کد به درستی رفتار میکند و اگر step تغییری کنید دوباره افکت اجرا می شود چون که یکی از وابستگی های این افکت هست. و در اکثر مواقع همون چیزی هست که مدنظر شماست. هیچ اشتباهی نیست که اگر step تغییر کرد افکت دوباره اجرا شود و interval از سر گرفته شود و ما نباید از این روش کار پرهیز کنیم مگر اینکه دلیل خوبی داشته باشیم.اما، بزارید در نظر بگیریم که ما نخواهیم interval مان از سرگرفته شود وقتی که step تغییری میکند. چگونه ما وابستگی step را از افکت مان حذف میکنیم؟وقتی شما یک state را تغییر میدهید بر اساس مقدار یک state دیگر، بهتره که useReducer  را امتحان کنید.بیاید وابستگی step را افکت مان حذف کنیم با استفاده از dispatch درون کدمان:ممکنه شما از خودتون بپرسید چجوری این کد می تونه بهتر از قبلی باشه؟ باید بگم که React تضمین کرده که تابع dispatch همیشه ثابت باشه در طول زمان کامپوننت مان، بنابراین افکت مان هیچ موقع مججد صدا زده نمی شود و interval دوباره subscribe نمی شود.خب ما مشکل را حل کردیم!و الان اگه بخواهیم کد reducer مان را ببینیم:این هم لینک کد هستچرا useReducer حالت تقلب برای Hooks استما تا الان تونسیم وابستگی را حذف کنیم در افکت هایی که وابسته به state قبلی یا یک state دیگر هست. اما اگه ما نیاز داشته باشیم که props محاسبه کنه وضعیت state بعدی مان را چیکار باید کرد؟ ممکن API کامپوننت ما به این صورت &lt;Counter step={1} /&gt; نوشته شده باشد. مطمئنان نمیشه توی این مورد props.step را از وابستگی حذف کرد؟در حقیقت ما می تونیم! می تونیم reducer را درون کامپوننت مان بنویسم تا بتونیم حذفش کنیم:این روش یکمی از نظر optimazation مشکل داره و نباید هرجایی از آن استفاده کرد اما در کل شما می توانی به props دسترسی داشته باشی در تابع reducer اگر نیاز شد.(اینم دمو)البته در این شرایط هم باز dispatch تضمین میشه که ثابت خواهد ماند بین رندر ها. بنابراین شما می توانید از وابستگی افکت تان حذف کنیدش. و باعث اجرای مجدد افکت نمی شود.شما ممکنه تعجب کنید چجوری این کد می تونه کارکنه؟ چجوری میشه reducer به props دسترسی داشته باشه حتی وقتی که درون یک افکت صدا زده می شود؟ هنگامی که شما dispatch می کنید، React فقط اکشن را یادش میمونه اما صدا خواهد زد reducer را در طول رندر بعدی، بنابراین props جدید درون اسکوپ reducer قابل دسترسی خواهد بود و شما درون افکت نخواهید بود.این دلیلی برای اینکه چرا من میگم useReducer تقلب برای هوک ها هست. چون علاوه بر اینکه جداسازی می کنه منطق اپدیت مان را از اتفاقی که رخ داده، کمک می کنه به حذف وابستگی ها و کمک می کنه به جلوگیری از اجرای مجدد افکت ها وقتی که نیازی بهشون نیست.انتقال تابع به درون Effectیک اشتباه متداول دیگر این هست که فکر می کنند تابع نمی تونه وابستگی به حساب بیاد. برای مثال به نظر میرسه این کد کار میکنه:اگه بخوایم کلی نگاه کنیم بله این تابع کار میکند. اما مسئله اینه که اگه توابع لوکال را به عنوان وابستگی در نظر نگیریم، با رشد کامپوننت و افزایش پیچیدگی آن، مدیریت وابستگی ها در مورد افکت مون سخت تر می شود.در نظر بگیریم کد مون یه چنین حالتی باشه ولی توابع تعداد خط کد های بیشتری داشته باشن(مثلا ۵ برابر اینا باشند):حالا مثلا بعدا بیایم به ریفکتور داشته باشیم و از Props و State درون یکی از این توابع استفاده کنیم:اگه ما فراموش کنیم که وابستگی ها مون رو اپدیت کنیم، افکت مان با تغییر props و state کامپوننت مان همگام سازی نمی شود و به نظر مشکل به وجود میاد.خوشبختانه، یه راه راحت برای حل این مسئله وجود داره، اگه این توابع که درون افکت مان صدا زده می شوند فقط دورن افکت مان استفاده شوند می توان آنها را مستقیم به افکت انتقال دهیم.خب مزیت این کار چیه؟ ما دیگه نیاز نیست در مورد وابستگی های غیر مستفیم فکر کنیم. الان آرایه وابستگی به ما دروغ نمی گوید. ما در حقیقت هیچی از اسکوپ کامپوننت مان درون افکت استفاده نمی کنیم.اگه ما بعدا بخوایم درون تابع getFetchUrl از query درون state کامپوننت مان استفاده کنیم. ما بیشتر دقت خواهیم کرد و متوجه می شویم که چون این تابع درون افکت هست باید وابستگی های این افکت را بروزرسانی کنیم.با اضافه کردن این وابستگی، ما نه تنها React رو خوشحال میکنیم، بلکه خیلی راحت متوجه می شویم که با تغییر کوئری مجددا داده ها را fetch میکنیم. اصلا طراحی useEffec، ما را بیشتر مجبور به دقت در مورد تغییراتی درون data flow مان می افتد میکنید و اینکه افکت مان چگونه باید بروز شود همراه با این تغییرات — به جای اینکه نادیده بگیریم و  منتظر بمانیم تا کاربران برنامه این باگ رو گزارش کنند.شما می تونید با استفاده از لینت exhaustive-deps  که درون ابزار eslint-plugin-react-hooks هست، کد ادیتورتون  شما را در هنگام کد نویسی متوجه این خطا کند، و به شما بگه که کدوم وابستگی در نظر گرفته نشده است یا توسط شما درون افکت handle نشده است.خیلی عالیه!اما من نمی تونم این تابع رو درون افکت قرار بدم!بعضی وقت ها شما نمی خواهید، که تابع تان را درون افکت قرار بدید مثلا از یک تابع در چند افکت استفاده میکنید یا اصلا اون تابع به عنوان props برای کامپوننت شما، فرستاده شده است.آیا باید این تابع را درون وابستگی های در نظر نگیریم، من چنین چیزی رو فکر نمی کنم.دوبار میگم، افکت نباید در مور وابستگی ها دروغ به گوید. یه راه بهتری که هست، یه تصور غلطی که وجود دارد اینه که تابع هرگز تغییر نمی کنه. اما الان به خاطر چیزی که از این مقاله یاد گرفتیم، این نمی تونه واقعیت باشه. در اصلا تابعی که درون کامپوننت مان تعریف می شود، در هر رندر تغییر میکند.این خودش یه مشکل به وجود میاره. این دو افکت را در نظر بگیرید که از تابع getFetchUrl استفاده میکنند:توی این مورد شما ممکن دوسته نداشته باشید که تابع getFetchUrl درون  توابع افکت مان قرار دهید، بخاطر اینکه اشتراک گذاری کد رو ازدست میدید.اما اگه شما بخواهید تابع getFetchUrl را به عنوان وابستگی افکت مان قرار بدید. چون هر دور افکت مان بستگی به این تابع دارند در هر بار رندر افکت مان صدا زده می شود و آرایه وابستگی بیهوده خواهد بود.یه راه حل دیگه اینه که اونو نادیده بگیریم و به عنوان وابستگی قرار ندیم. اما فکر نکنم راه حل خوبی باشه. این باعث میشه کمتر توجه کنیم به وابستگی های افکت مان در مواقع ایجاد تغییر درون این کد و همان باگ بروز نشدن interval خواهد شد که قبلا دیدیم:در عوض دو تا راه حل وجود داره که ساده ترند.تابعی که چیزی درون اسکوپ کامپوننت مان استفاده نمی کند. می تونیم بیرون از کامپوننت تعریق کنیم و از آن استفاده کنیم:نیاز به تعیین هیچ وابستگی در آرایه نیست بخاطر اینکه درون اسکوپ رندر مان نیست و نمی تواند تاثیر برای دیتا فلوی کامپوننت مان بگذارد و نمی توان به صورت اتفاقی props و state مان را تغییر دهد.شما همچنین می توانید درون هوک useCallback قرار بدهید:شما می تونید useCallback رو یه لایه اضافه برای چک کردند وابستگی در نظر بگیرید. این مسئله را از روی دیگر مشکل مون حل میکند - به جای اینکه جلوگیری کند از وابستگی تابع مون، باعث میشه تابع مون تغییر کنه تنها وقتی که نیاز هست.بزارید این راه حل رو امتحان کنیم. قبلا، مثال مون دوتا نتیجه جستجو داشت(کوئری برای &#x27;react&#x27; و &#x27;redux&#x27; ). اما بزارید یه input قرار بدیم و شما برای هر کوئری که خواستید جستجو کنید. بنابراین بجای اینکه کوئری مون رو از آرگومان تابع getFetchUrl بگیریم، از state مون میگیریم.به محض انجام این کار شما پیغام خطای ازدست دادن وابستگی را مشاهده میکنید:اما اگه من در وابستگیuseCallback  کوئری مون قرار بدم، هر افکتی که تابع getFetchUrl رو در وابستگی هاش استفاده میکنه دوباره اجرا می شود با هر تغییر کوئری:دمت گرم useCallback. اگه کوئری مون ثابت باشه تابع getFetchUrl دوباره ساخته نمیشه و افکت مان دوباره صدا زده نمی شود. اما اگه کوئری مون تغییر کنه، تابع getFetchUrl هم تغییر میکنه  و دوباره داده ها را در افکت مان Fetch خواهد شد.این روش برای تابعی که از طریق Props ، برای کامپوننت فرزند ارسال می شود نیز جواب میدهد:از اونجایی که تابع fetchData درون کامپوننت پدر، تنها فقط با تغییر کوئری تغییر میکند در نتیجه کامپوننت فرزند تا کوئری تغییر نکند داده ها را فچ نمی کند.آیا توابع جزئی از جریان داده ها(Data Flow) هستند؟جالبه که این الگو توسط کلاس ها شکسته شده است به روشی که تفاوت افکت (Effect) و چرخه زمان (Life cycle) ها را بهتر مشاهده میکنید:شما ممکنه بگید: بابا دست بردار ما همه، میدونیم که  useEffect ترکیب هر دو تابع componentDidMount و componentDidUpdate است. اما باید بگم که این کد حتی با componentDidUpdate هم کار نمی کند:البته که، fetchData  یه متود کلاس هست! این هیچ موقع تغییر نمیکنه بخاطر تغییر state مون. بنابراین this.props.fetchData  با prevProps.fetchData برابر می مونه و داده ها دوباره فچ نمی شوند.بزارید شرط رو حذف کنیم: یه لحظه صبر کن، این که همیشه فچ می شود در هر رندری. خب بزارید بایندش کنیم با یه کوئری خاص:اما this.props.fetchData !== prevProps.fetchData همیشه درست هست باز در هر رندر فچ کردند رو داریم.تنها راه حل این مشکل پیچیده که با کلاس ها به وجود میاد فرستادن کوئری به عنوان props به کامپوننت فرزند و مشخص کردن زمان فچ کردن دوباره، با استفاده از کوئری هست:پس از سالها کار کردن با ری اکت [من نمیگم Dan میگه]، من مجبور بودم که این کار رو انجام بدم و هفته پیش فهمیدم چرا مجبورم انجام بدم.در کلاس ها، متود ها خودشون واقعا جز جریان داده ها نیستند. آن ها محدود هستن به یک this، که از نوع mutable هست. با useCallback ، توابع دقیقا در جریان داده ها هستند. ما می تونیم بگیم که اگر ورودی تابع تغییر کند، خود تابع هم تغییر میکند، وگرنه ثابت می ماند. دستت درد نکن useCallback که این امکان رو برای ما فراهم آوردی که تغییرات در props.fetchData کاملا باعث تاثیر اتوماتیک در کامپوننت مان می شود.مشابه آن،useMemo است که می تونیم برای یک ابجکت پیچیده بکار ببریم:البته می خوام تاکید کنم که قرار دادن هوک useCallback برای هر تابعی کاملا نادرست است.البته من در مثال های بالا ترجیح میدم تابع ام رو یا درون افکت قرار بدم یا به عنوان کاستوم هوک استفاده کنم یا اینکه import کنم. من میخوام که افکت ها ساده باشند و callback تو این قضیه کمکی نمی کنه.صحبت در مورد Race Conditionsنحوه ی ساده فچ کردن دیتا ها در کلاس کامپوننت ها به این صورت هست:همینجوری که میدونید این کد مشکل داره و با بروزرسانی id داده ها دوباره فچ نمی شوند.مطمئنا این کاملا بهتر هست، اما باز هم مشکل داره و ترتیب ریکوئست هامون ممکنه بهم بریزه. مثلا اگه ما بیایم داده ها را برای {id: 10} بگیریم، و تغییر بدیم به {id: 20} اما ریکوئست {id: 20} نتیجه آن زودتر بیاید و ریکوئستی که زودتر فرستاده بودیم و قدیمی تر بود نتیجه اش دیرتر بیاید به صورت کاملا اشتباه state مون رو تغییر میدند.به این مشکل Race conditions میگند که معمولا در توابع async / await رخ میدهد. افکت ها به صورت عجیب غریب کد شما رو برای این مورد درست نمی کند بلکه به شما هشدار میدهد اگه بخواهید مستقیما دون افکت از توابع async استفاده کنید.اگه این تابع async یه راهی برای کنسل کردن هم داشته باشد. خیلی عالیه و میتوان  در تابع cleanup آن را کنسل کرد.یه راه خیلی ساده کنسل کردن میتونه به این صورت پیاده سازی بشه:پایانحالا شما هر آنچه را که من درمود افکت ها میدونم میدونید.بالاخره تموم شد چند روزی سرم شلوغ بود و زمان ها کوتاهی فرصت میکردم که این مقاله را ادامه اش رو بنویسم ارزشش رو داشت حداقل برای خودم که عمیق تر فهمیدم انتشارش میدم که بقیه هم اگه خواستند استفاده کنند البته من ، مترجم نیستم و این مقاله نیاز به خیلی اصطلاحات تخصصی داشت که تا اونجایی که بود سعی کردم ساده توضیح بدهم اگه بد ترجمه شده بود ببخشید اگه جایی به نظرتون ایراد داره حتما بگید و اینکه اگه  جایی معادل بهتر پیدا کردید حتما بگید تا جایگزین کنم سوالی هم اگه بود تا اوناجایی که دانش بنده جواب بده جواب میدم.</description>
                <category>حسین شیره جونی</category>
                <author>حسین شیره جونی</author>
                <pubDate>Mon, 18 May 2020 22:58:46 +0430</pubDate>
            </item>
                    <item>
                <title>کاهش مصرف رم سایت با استفاده از yield در PHP</title>
                <link>https://virgool.io/@shirejoni/yield-in-php-memory-performance-rzcgxkvfexva</link>
                <description>آیا در مورد yield در PHP چیزی شنیدید؟ خب من در وقتتون صرفه جویی میکنم و نیازی نیست برید سرچ کنید با سرفصل زیر در مورد yield صحبت می کنیممعرفی yield.تفاوت بین yield &amp; return.خصوصیات yield.نتیجه گیری.معرفی yieldبزارید یه تابع تعریف کنیم مثل بقیه توابع ولی به جای return کردن yield میکنیم مانند:function getValues() {
    yield &#039;value&#039;;
}

// print the string &quot;value&quot;
echo getValues();خب مسلماَ، این کد کار نمی کنه به شما یه fetal error بر میگردونه: object of class Generator could not be converted to stringبزارید ارور رو توضیح بدیم:تفاوت بین yield &amp; returnاروری که بالا نوشتم میگه تابعمون string باید return میکرده ولی یه object فرستاده!!! اگه بخوایم تایپ شون رو بفهمیم:function getValues() {
    return &#039;value&#039;;
}
var_dump(getValues()); // string(5) &quot;value&quot;

function getValues() {
    yield &#039;value&#039;;
}
var_dump(getValues()); // class Generator#1 (0)کلاس Generator یه کلاسی هست که implement میشه از اینترفیس Iterator: یعنی باید از تابع  getValues در حلقه ها استفاده کنیم:foreach (getValues() as $value) {
    echo $value;
}
// using variable is also alright
$values = getValues();
foreach ($values as $value) {
    echo $value;
}
البته این تنها تفاوتش نیستیه Generator بهت اجازه میده از حلقه ها برای یه دسته از داده ها استفاده کنی بدون اینکه آرایه ای تعریف کنی و این یعنی آرایه ای نیست که در  رم ذخیره کنه و در نتیجه مصرف رم کمتر!برای درک بهتر استفاده از yield فکر کنید یه آرایه داریم با 800,000 ایندکس و بخوایم با تابعی مثل تابع بالا return کنیم و اگر با تابع memory_get_usage() میزان رم را اندازه گیری کنیم، من در هر 200,000 المنت اندازه گیری کردم و نتیجه اش:0.34MB
8.35MB
16.35MB
32.30MBخب بخاطر چند تا خط کد، اسکریپتمون بخواد 30 مگ حافظه مموری رو اشغال کنه یعنی هر بار صدا کردن آرایه این مقدار در مموری افزایش پیدا میکنه اما اگه از yield برای همین مثال استفاده کنیمنتیجه:0.34MB
0.34MB
0.34MB
0.34MBمتوجه تفاوت فاحش این دو کد میشید اما این به این معنی نیست که از return به yield مهاجرت کنیم اما اگه از یه آرایه سنگین در کدتون استفاده می کنید گزینه مناسب همین yield خواهد بودخصوصیات yieldمن یه چندتا از خصوصیات yield رو اینجا براتون میگم(مهماش!)آ. می تونید yield و return رو باهم استفاده کنید:function getValues() {
    yield &#039;value&#039;;
    return &#039;return value&#039;;
}
$values = getValues();
foreach($values as $value) {}
echo $values-&gt;getReturn();// &#039;retrun value&#039;ب. برگرداندن به حالت key/valuefunction getValues() {
    yield &#039;key&#039; =&gt; &#039;value&#039;;
}
$values = getValues();
foreach($values as $key =&gt; $value) {}اطلاعات بیشتر در اینجانتیجه گیریهدف این مقاله بیان تفاوت بین yield و retrun بود و زدن چند تا مثال برای درک بهتر yieldامیدوارم بدردتون خورده باشه (ترکیبی از ترجمه یه مقاله و خودم)لطفا در مورد اولین مطلب نظراتتون رو بدید و اگر عنوان یا مبحثی مد نظرتون پیشنهاد دهیدیا حق</description>
                <category>حسین شیره جونی</category>
                <author>حسین شیره جونی</author>
                <pubDate>Wed, 23 May 2018 20:10:52 +0430</pubDate>
            </item>
            </channel>
</rss>