<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>پست‌های انتشارات جامعه توسعه دهندگان ری‌اکت ایران</title>
        <link>https://virgool.io/iran-react-community/feed</link>
        <description>جامعه غیر انحصاری توسعه دهندگان React JS و React Native ایران</description>
        <language>fa</language>
        <pubDate>2026-06-10 17:29:12</pubDate>
        <image>
            <url>https://files.virgool.io/upload/publication/4gpxrvaypvu7/ixz4vu.png</url>
            <title>جامعه توسعه دهندگان ری‌اکت ایران</title>
            <link>https://virgool.io/iran-react-community</link>
        </image>

                    <item>
                <title>چگونه در React حمله XSS بخوریم!</title>
                <link>https://virgool.io/iran-react-community/xss-in-react-yvpqg3f36zwn</link>
                <description>میدانیم که XSS یک آسیب‌پذیری امنیتی وب است که به مهاجم امکان اجرای کدهای مخرب جاوااسکریپتی را در مرورگر قربانی می‌دهد که می تواند کاربر را به سایت‌های مخرب هدایت کند یا در سایت خرابی‌هایی را ایجاد کند.خوشبختانه React چند کار برای محافظت از برنامه ما در برابر حملات XSS انجام می‌دهد. React عناصر و داده‌های داخل آن را با استفاده از auto escaping خروجی می‌دهد.همه چیز در داخل عنصر را بعنوان یک رشته تفسیر می‌کند و هیچ عنصر اضافی را ارائه نمی‌کند.این بدان معناست که اگر مقدار داخل عنصر به نحوی توسط یک attacker با برخی تگ‌های  نفوذ می‌کرد، React به‌سادگی آن را نادیده می‌گرفت و آن را بعنوان یک رشته در نظر می‌گرفت.خروجی کد بالا در مرورگرهمانطور که مشاهده می‌کنید کاربر بعد از فشردن دکمه تایید متن را تغییر داد ولی تگ &lt;b&gt; به‌صورت رشته چاپ شد.dangerouslySetInnerHTMLبعضی مواقع نیاز است یک کلمه از یک رشته متن را تفییر دهیم برای مثال آن را bold کنیم یا اینکه رنگ یا فونت آن را تغییر دهیم.در اینجور مواقع تکه تکه کردن متن و استایل دهی به تک تک آن‌ها باعث می‌شود کدهای بیشتری بنویسیم و کد تمیزی نداشته باشیم.یکی راه حل برای این موضوع استفاده از ویژگی dangerouslySetInnerHTML است.هنگامی که از dangerouslySetInnerHTML استفاده می‌شود، React از مقایسه با virtual DOM صرف نظر می‌کند.همانطور که از نامش پیداست استفاده از آن می‌تواند خطرناک باشد زیرا کد ما به‌راحتی در برابر حملات XSS قرار میگیرد:خروجی کد بالا در مرورگردر کد بالا سعی کردیم کلمات &quot;نام کاربری&quot; و &quot;گذرواژه&quot; را با استفاده از تگ &lt;b&gt; به شکل bold چاپ کنیم.برای تگ &lt;b&gt; یک رویداد  نوشتیم که وقتی نشانگر ماوس روی کلمات bold شده قرار گرفت یک alert را نمایش دهد.حالا ما یک آسیب پذیری XSS در سایت خود داریم که مهاجم با استفاده از آن می‌تواند کد جاوااسکریپتی خود را اجرا کند.نحوه پیشگیریاگر مجبور به استفاده از dangerouslySetInnerHTML در کدهای خود هستید بهتر است از یک کتابخانه sanitizer خوب استفاده شود که تا حدی اطمینان حاصل می‌کند کد تمیز است و اسکریپت‌های غیرمنتظره را هنگام رندر در React node اجرا نمی‌کند.تعدادی کتابخانه‌ی sanitizer وجود دارد اما قبل از انتخاب یکی از آن‌ها مزایا و معایب آن‌ها را درنظر بگیرید.از نوشتن روش‌های sanitization خودتان خودداری کنید.createRefاز createRef برای دسترسی به یک کامپوننت یا عنصر DOM و ذخیره کردن آن در یک متغیر استفاده می‌شود.مثلا برای مدیریت focus یا انتخاب یک متن و تغییر آن.خروجی کد بالا قبل از ۲ ثانیهخروجی کد بالا پس از ۲ ثانیه و تغییر متن با استفاده از innerHTMLهمانطور که در کد بالا مشاهده میکنید بعد از اینکه DOM کامپوننت بارگیری می‌شود(mount می‌شود) پس از ۲ ثانیه با استفاده از innerHTML به راحتی می‌شود متن عنصر div را تغییر داد.یک attacker می‌تواند بدون درنظر گرفتن عنصر div  اسکریپت مخرب خود را در داخل useEffect تزریق کند و خرابی‌هایی را به‌بار آورد. نحوه پیشگیریسعی کنید DOM را مستقیما تغییر ندهید.اگر احتیاج به تغییر محتوا بدون رندر اضافی دارید بهتر است از innerText به‌ جای innerHTML استفاده شود.همیشه سعی کنید داده‌ها را از طریق JSX ارائه دهید زیرا React تا حد خوبی مسائل امنیتی را مدیریت می‌کند.</description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>معصومه قنبری</author>
                <pubDate>Sun, 12 Dec 2021 21:21:43 +0330</pubDate>
            </item>
                    <item>
                <title>انواع روش ها  برای بهبود کارایی اپلیکیشن های ری اکت جی اس(React.js)قسمت اول</title>
                <link>https://virgool.io/iran-react-community/%D8%A7%D9%86%D9%88%D8%A7%D8%B9-%D8%B1%D9%88%D8%B4-%D9%87%D8%A7-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%A8%D9%87%D8%A8%D9%88%D8%AF-%DA%A9%D8%A7%D8%B1%D8%A7%DB%8C%DB%8C-%D8%A7%D9%BE%D9%84%DB%8C%DA%A9%DB%8C%D8%B4%D9%86-%D9%87%D8%A7%DB%8C-%D8%B1%DB%8C-%D8%A7%DA%A9%D8%AA-%D8%AC%DB%8C-%D8%A7%D8%B3reactjs%D9%82%D8%B3%D9%85%D8%AA-%D8%A7%D9%88%D9%84-kmug8dzzjftv</link>
                <description>کتابخانه ری اکت (ReactJS)بی نظیر است برای تمام نواقص و مشکلات احتمالی یک راه حل بهینه دارد که در این مقاله میخواهم 5 روش برای بهبود کارایی و سرعت اپلیکشین های React.js را به صورت موردی مطرح کنم و در قسمت دوم موارد بعدی را بررسی کنم1.React.memoاگر با React.PureComponent   آشنا باشید، در این صورت React.memo برای شما کاملاً سرراست خواهد بود،  زیرا کاملاً مشابه React.PureComponent است. ما از React.PureComponent با  کامپوننت کلاس استفاده می‌کنیم، اما React.memo به همراه کامپوننت‌های تابع  عمل می‌کند.const App = () =&gt; {
   const [count1, setCount1] = React.useState(0)
   const [count2, setCount2] = React.useState(0)

   const increaseCounter1 = () =&gt; {
      setCount1(count1 =&gt; count1 + 1)
   }

   return (
      &lt;&gt;
         &lt;button ={increaseCounter1}&gt;Increase counter 1&lt;/button&gt;
         &lt;Counter value={count1}&gt;Counter 1&lt;/Counter&gt;
         &lt;Counter value={count2}&gt;Coutner 2&lt;/Counter&gt;
      &lt;/&gt;
   )
}
const Counter = ({value, children}) =&gt; {
   console.log(&#039;Render: &#039;, children)

   return (
      &lt;div&gt;
         {children}: {value}
      &lt;/div&gt;
   )
}


export default Counterهر بار که کاربر روی دکمه کلیک می‌کند، حالت count1 تغییر می‌یابد و  موجب می‌شود که اپلیکیشن هر دو شمارنده را رندر مجدد کند که این رندرها به  عنوان «رندر مجدد غیرضروری» شناخته می‌شوند. با این حال، ما صرفاً انتظار  داریم که counter1 رندر مجدد شود، چون هیچ چیزی در مورد counter2 تغییر  نخواهد یافت. در عمل، هر دو شمارنده رندر مجدد می‌شوند.چگونه می‌توانیم این مشکل را رفع کنیم؟ پاسخ در React.memo است. تنها  چیزی که نیاز داریم این است که کامپوننت شمارنده را درون React.memo قرار  دهیم.const Counter = ({value, children}) =&gt; {
   console.log(&#039;Render: &#039;, children)

   return (
      &lt;div&gt;
         {children}: {value}
      &lt;/div&gt;
   )
}

export default React.memo(Counter)ری اکت ممو(React.memo)به صورت پیش‌فرض همه props ارسالی به کامپوننت را از طریق referential  equality مقایسه می‌کند. اگر این props تغییری نیافته باشند، React.memo از  آخرین نتیجه رندر مجدد شده استفاده می‌کند و از این رو از رندر شدن مجدد  کامپوننت جلوگیری می‌کند.2.use.Memoیکی از هوک های ریکت (React Hook) می باشد که برای کار با کش (cache) در اپلیکیشن های ری اکت بکار می رود.توضیح خود را با بیان تعریف از مستندات رسمی آغاز می‌کنیم. useMemo یک مقدار «درون حافظه‌ای» (memoized) بازگشت می‌دهد.React.useMemo(() =&gt; {
  fooFunction()
}, [dependencies])const App = () =&gt; {
   const fooFunction = () =&gt; {
      return &#039;Foo is just Food without D&#039;
   }

   const useMemoResult = React.useMemo(fooFunction, [])

   console.log(&#039;useMemoResult: &#039;, useMemoResult)

   return &lt;p&gt;Foo is just food without D&lt;/p&gt;
}یوز ممو (React.useMemo) اقدام به فراخوانی fooFunction می‌کند و نتیجه‌اش را بازگشت می‌دهد3.React.PureComponentیک کلاس  کامپوننت base است که تمام فیلدهای state و props را چک می کند و در  صورتی که تغییر پیدا کنند کامپوننت آپدیت خواهد شد. در غیر اینصورت رندر  نخواهد شد.درست مانند کاری که متد shouldComponentUpdate در کلاس کامپوننت انجام می دهد، React.PureComponent نیز همینکار را می کند.4.shouldComponentUpdateبه طور پیش فرض این متد پیاده  سازی شده نیست، پس هر تغییر توی props یا states باعث میشه کامپوننت  re-render بشه، هنگامی که کامپوننت تصمیم به تغییر یا بروزرسانی DOM را دارد،این متد فراخوانی می شود.این متد به ما اجازه می دهد تا رفتار کامپوننت را در بروزرسانی آن کنترل  کنیم.بدین صورت که اگر این متد مقدار true را بازگرداند،کامپوننت  بروزرسانی خواهد شد،در غیر اینصورت از بروزرسانی کامپوننت صرف نظر خواهد  کرد.در shouldComponentUpdate نمیتونیم از setState استفاده کنیم.5.استفاده از سلکتورهای reselectریداکس به شکل immutable کار می کند, به این معنی که با هر بار  dispatch شدن action رفرنس های جدیدی از آبجکت تعریف می شود. این قضیه باعث  کاهش بهره وری و کارایی نرم افزار خواهد شد. زیرا حتی اگر رفرنس آبجکت  تغییر کند، کامپوننت re-render می شود. با اینکه فیلدهای آبجکت تغییر نکرده  اند.لایبرری Reselect state ریداکس را کپسوله  سازی یا encapsulate می کند و چک خواهد کرد که هر زمان مقدار فیلدهای آبجکت  state تغییر کرد کامپوننت مجددا رندر شود.بنابراین reselect باعث  می شود در زمان اجرای اپلیکیشن صرفه جویی شود. به این صورت که مقدار  state قبل و بعد را چک می کند و اگر تغییر پیدا کرده بود کامپوننت  re-render خواهد شد. وگرنه با تغییر رفرنس آبجکت state کامپوننت رندر  نخواهد شد.قسمت دوم https://vrgl.ir/6JNq3</description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>امیرمسعود گراوند</author>
                <pubDate>Tue, 21 Sep 2021 13:32:12 +0430</pubDate>
            </item>
                    <item>
                <title>کتابخانه ی ReactJS چیست و چه کارهایی می توان با آن انجام داد؟</title>
                <link>https://virgool.io/iran-react-community/%DA%86%DB%8C%D8%B3%D8%AA-%D9%88-%DA%86%D9%87-%DA%A9%D8%A7%D8%B1%D9%87%D8%A7%DB%8C%DB%8C-%D9%85%DB%8C-%D8%AA%D9%88%D8%A7%D9%86-%D8%A8%D8%A7-%D8%A2%D9%86-%D8%A7%D9%86%D8%AC%D8%A7%D9%85-%D8%AF%D8%A7%D8%AF-reactjs-jkwe0w661tu2</link>
                <description>در سال ۲۰۱۱ این کتابخانه را تحت تاثیر XHP که یک کامپوننت Html برای زبان برنامه نویسی PHP‌ است، ایجاد شده است و در همین سال React روی قسمت  News Feed شبکه اجتماعی فیسبوک به کار گرفته شد و ۲ سال بعد، یعنی در سال  ۲۰۱۳ هم استفاده از آن توسط فیسبوک به اینستاگرام تعمیم پیدا کرد.ری اکت یک کتابخانه متن باز (Open source) جاوا اسکریپت است که  به دلیل بهینه بودن React.js برای دریافت اطلاعاتی که با سرعت تغییر می‌کنند، می‌توان از آن برای توسعه برنامه ی تک صفحه ایی(SPA) یا برنامه‌های موبایل استفاده کرد, یکی از سریع‌ترین و محبوب‌ترین کتابخانه‌ها (Library) جاوا اسکریپت است که  توسط فیسبوک اینستاگرام و یک جامعه مستقل از توسعه دهندگان وب مدیریت و  نگهداری می‌شود.براساس آنالیزهای جاوااسکریپت سرویس لیبسکور، ری‌اکت در حال حاضر در سایت‌های نت فلکس، ایمجر، بلیچر ریپورت، فیدلی، ایر بی ان بی و … مورد استفاده قرار می‌گیرد.نکته مهم در کاربرد React.js سادگی و یادگیری آسان آن است و همچنین این کتابخانه صرفا در الگوی طراحی  MVC، عهده‌دار بخش View است. View یا اینترفیس در واقع مرتبط با نمایش اجزا  هست و طبعا React.js به جای پرداختن به الگوی MVC به وظایفی می‌پردازد  که مربوط به نمایش اجزا است.کتابخانه React.js این قابلیت را برای  برنامه نویسان می دهد تا برنامه های کاربردی تحت وب طراحی کنند که بدون  بارگزاری مجدد صفحه می توان اطلاعات آن را تغییر داد. هدف اصلی کتابخانه React.js سریع بودن، قابل توسعه بودن و ساده بود و مقیاس پذیر بودن آن است, ما می توانیم عناصر رابط کاربری مانند یک  دکمه یا یک قسمت ورودی را به عنوان یک کامپوننت ری اکت بنویسیم. یک  کامپوننت ممکن است یک یا چند کامپوننت دیگر را در خروجی خود داشته باشد و می توانیم کامپوننت هایی با قابلیت استفاده مجدد نیز طراحی و ایجاد کنیم. حال برخی از ویژگی های React.js را بررسی می کنیم:جی اس ایکس(jsx) در React.jsدر React.js ، برای قالب بندی به جای  استفاده از جاوا اسکریپت معمولی از JSX استفاده می شود. JSX یک جاوا  اسکریپت ساده است که از HTML پیروی می کند و از این دستورات تگ HTML برای  ارائه زیر کامپوننت ها در React استفاده می کند. زبان HTML به منظور پاسخ  به فراخوانی های جاوا اسکریپت از سوی کتابخانه ی React پردازش شده است. در  اینجا ما حتی می توانیم به زبان خالص قدیمی جاوا اسکریپت نیز کد بنویسیم.جریان اطلاعات تک خطی در React.jsدر React.js ، مجموعه ای از متغیرهای  غیرقابل تغییر به عنوان مشخصه هایی در تگ های HTML خود به ارائه دهنده  کامپوننت ها منتقل می شوند. کامپوننت ها نمی توانند به طور مستقیم هر خواصی  را تغییر دهند اما می توانند بازگشتی یک تابع فراخوانی شده را قبول کنند  بدین ترتیب ما می توانیم تغییرات خود را اعمال کنیم. تمام این فرآیند ها به  شرح فوق شناخته شده اند: “جریان خاصیت ها کاهش می یابد ، جریان واکنش ها  افزایش می یابد”.پراپس ها در React.jsپراپس ها باعث می شوند که مجموعه کامپوننت  ها بتوانند از داده های سفارشی استفاده کنند. پراپس ها در React.js این  امکان را فراهم می کنند تا داده های سفارشی به یک UI سفارشی انتقال خاصی  انتقال پیدا کنند.ری اکت جی اس از DOM مجازی برای سرعت بخشیدن به برنامه استفاده می کنداین ساختار که به اختصار Virtual DOM نامیده می‌شود، ابتدا تغییرات انجام  شده را محاسبه کرده و سپس مرورگر کاربر را آپدیت می‌کند. این ویژگی به طراح  سایت و توسعه دهنده این امکان را می‌دهد که به گونه‌ای کد نویسی کند که  انگار تمام صفحه با هر تغییر رندر می‌شود، در حالی که در واقع کتابخانه  React تنها کامپوننت‌هایی را رندر می‌کند که واقعا تغییر کرده‌اند.ویژگی Single-Way data flowدر React.js، مجموعه‌ای از value های تغییر ناپذیر بین کامپوننت‌ها به عنوان ویژگی‌هایی(properties) در برچسب‌های HTML منتقل می‌شوند.  کامپوننت‌ها به طور مستقیم نمی‌توانند هیچ یک از ویژگی‌ها (properties) را  تغییر دهند اما میتوان آن‌ها را به call back function انتقال دهند و به  کمک آن‌ها تغییرات را انجام دهند. این فرآیند به طور کامل با “properties  flow down; actions flow up” شناخته می‌شود.اگر دلتان می‌خواهد یک تکنولوژی جدید یاد بگیرید که در تمام دوران حرفه‌ای وکاری  خود از دانستن آن به خود ببالید، به شما پیشنهاد می‌کنم React.js را یادبگیرید امیدوارم متوجه شده باشید React.js چیه و بتونید با یادگیری این کتابخانه به توسعه پروژه های خودتون بپردازید و موقعیت های شغلی خوبی بدست بیارید.</description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>امیرمسعود گراوند</author>
                <pubDate>Mon, 20 Sep 2021 23:04:07 +0430</pubDate>
            </item>
                    <item>
                <title>آموزش fragment در React</title>
                <link>https://virgool.io/iran-react-community/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-fragment-%D8%AF%D8%B1-react-iegagclqqkb2</link>
                <description>سلام به همه عاشقان ریکتتو ریکت یه مبحثی به نام Fragment وجود داره که ممکنه تو خیلی از کامپوننت ها بهش نیاز داشته باشین.بحث Fragment بر خلاف اسم گلمبه ای که داره، مفهوم خیلی ساده و قابل فهمی داره.خب بریم ببینیم چه خبره...همون طور که میدونین هر کامپوننت تو ریکت فقط میتونه یه تگ والد رو return کنه، هم کلاس کامپوننت ها و هم فانکشنال کامپوننت ها.فرض کنین میخوایم یه کامپوننت واسه table ایجاد کنیم و واسه ایجاد td های اون از یه کامپوننت به اسم Column استفاده کنیم.کامپوننت Columnکامپوننت Tableخب همون طور که میبینین واسه ایجاد td ها از کامپوننت Column استفاده کردیم و انتظار داریم td های لازم رو برامون ایجاد کنه.اما کامپوننت Column مجبوره که tdها رو داخل یه تگ والد returnکنه تا ریکت خطای نده.خروجی Table اینطوری میشه:ولی این خروجی قابل قبول و مورد نظر ما نیست.اینجاست که Fragment میاد وسط.بعضی وقتا ممکنه بخواین تو یه کامپوننتی چندین تگ رو return کنین ولی ریکت بهتون خطا میده، اگه تو div هم بذارین ممکنه به مشکل بخورین!تو همچین مواقعی میتونین از React.fragment استفاده کنین.خب React.fragment این امکان رو بهتون میده که تو یه کامپوننت، چندین تگ رو بدون نیاز به والد return کنین.کافیه تگ هایی رو که میخواین return کنین، بذارین تو تگ React.fragment.کامپوننت Column رو به شکل زیر تغییر میدیمکامپوننت Columnبه این ترتیب خروجی کامپوننت Table به این شکل خواهد بود:به همین راحتی مشکلمون حل میشه.یه شورتکات واسه React.fragmentشما میتونین به جای React.fragment از یه تگ خالی استفاده کنین:به همین راحتی ?اتربیوت key تو React.fragmentاگه اطلاعات مربوط به template کامپوننتتون تو یه آرایه باشه و بخواین با متدی مثل map آرایه رو پیمایش کرده و تمپلیت رو return کنین، باید به React.fragment اتربیوت keyبدین(مثل قبلا که برای تگ والد template کامپوننتتون از keyاستفاده می کردین.)نکته مهم: اتربیوت key تنها اتربیوتی هست که میتونین به React.fragment پاس بدین و به جز key نمیتونین اتربیوت دیگه ای استفاده کنین.طبق گفته خود تیم ریکت، در آینده اتربیوت های دیگه ای مثل Event Handler ها به React.fragment اضافه خواهد شد.خب...امیدوارم این مقاله براتون مفید واقع شده باشه.اگه پیشنهاد یا انتقادی دارین، خوشحال میشم کامنت کنین.تا مقاله بعدی خدانگهدار :)</description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>یوزرکد</author>
                <pubDate>Mon, 01 Mar 2021 20:25:42 +0330</pubDate>
            </item>
                    <item>
                <title>استقرار پروژه‌های React با استفاده از Nginx و گواهی SSL</title>
                <link>https://virgool.io/iran-react-community/%D8%A7%D8%B3%D8%AA%D9%82%D8%B1%D8%A7%D8%B1-%D9%BE%D8%B1%D9%88%DA%98%D9%87-%D9%87%D8%A7%DB%8C-react-%D8%A8%D8%A7-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-nginx-%D9%88-%DA%AF%D9%88%D8%A7%D9%87%DB%8C-ssl-g0yx78u6grno</link>
                <description>استقرار پروژه‌های ریکتپروژه‌های مبتنی بر React خودت رو کمتر از 5 دقیقه Deploy کن!توی این نوشته، با استفاده از Nginx و letsencrypt ، پروژه‌های React یا Next js خودمون رو زیر 5 دقیقه روی یک سرور لینوکس، deploy می‌کنیم.? شما از قبل بایستی یک سرور لینوکس ( که ما اینجا از اوبونتو استفاده می‌کنیم ) تهیه کرده باشید و از طریق SSH به اون متصل بشید. همچنین نیاز به آخرین ورژن npm و nodejs روی سرور خودتون دارید.1️⃣ نصب nginx و letsencrypt بر روی سرور$ sudo apt-get update
$ sudo apt-get install nginx letsencrypt2️⃣ ویرایش تنظیمات پیش‌فرض nginx$ sudo vim /etc/nginx/sites-available/defaultکه محتوای زیر رو در اون تغییر می‌دیم و به جای &lt;your_domain&gt; ، نام دامنه خودمون رو قرار می‌دیم.server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/html;
    index index.html index.htm index.nginx-debian.html;

    server_name &lt;your_domain&gt;;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ /.well-known {
        allow all;
    }
}و با دستور زیر nginx رو ریستارت می‌کنیم.$ sudo systemctl restart nginx3️⃣ راه‌اندازی letsencrypt برای ایجاد گواهی SSL$ sudo letsencrypt certonly -a webroot --webroot-path=/var/www/html -d &lt;your_domain&gt; -d www.&lt;your_domain&gt;
$ sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048ایجاد فایل کانفیگ nginx برای SSL$ sudo vim /etc/nginx/snippets/ssl-params.confکه محتوای زیر رو قرار می‌دیم:ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers &amp;quotEECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH&quot;
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;

resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;

add_header Strict-Transport-Security &amp;quotmax-age=63072000; includeSubdomains&quot;
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

ssl_dhparam /etc/ssl/certs/dhparam.pem;و در نهایت فایل کانفیگ nginx خودمون رو مجددا ویرایش می‌کنیم:server {
  listen 80 default_server;
  listen [::]:80 default_server;
  server_name &lt;your_domain&gt; www.&lt;your_domain&gt;;
  return 301 https://$server_name$request_uri;
}

server {
  listen 443 ssl http2 default_server;
  listen [::]:443 ssl http2 default_server;

  server_name &lt;your_domain&gt;;
  
  ssl_certificate /etc/letsencrypt/live/&lt;your_domain&gt;/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/&lt;your_domain&gt;/privkey.pem;
  include snippets/ssl-params.conf;

  location / {
   # reverse proxy for node server
    proxy_pass http://localhost:5000;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection &#039;upgrade&#039;;
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;
  }
  
  location ~ /.well-known {
    allow all;
  }
}چند نکته راجع به فایل کانفیگ nginx رو بهش اشاره کنم:? بسته به پروژتون next، react یا ... و port ای که برای run شدنش انتخاب کردید، در خط 20 اون رو تغییر بدید.?  در خط اول تا ششم هم ما یه ریدایرکت از http به https داریم.? در خط 14 و 15 هم به جای your_domain، نام دامنه‌ای که در هنگام راه‌اندازی letsencrypt وارد کردید را قرار دهید.? هر دو پورت 80 و 443 هم بایستی روی سرورتون باز باشه.و در آخر دوباره سرویس nginx رو restart می‌کنیم:$ sudo service nginx restart4️⃣ اجرای پروژه ( run کردن )در ابتدا پروژه‌ی خودتون رو از طریق git روی سرور clone کنید. اگر موفق نشدید، احتمالا نیاز به set کردن dns روی سرور دارید.سپس برای ران کردن پروژه و برقراری اجرای آن پس از بسته شدن session اتصال به سرور، نیاز به دستور screen دارید که می‌تونید از طریق لینک زیر راجع بهش بخونید.? آموزش و کار با دستورات screenبرای مثال من یک دستور screen برای ران کردن پروژه‌‌ی react رو می‌نویسم که مشابه همین برای next هم می‌تونید استفاده کنید:$ sudo npm run build
$ sudo screen serve -s build? کار ما تمام شد!هم‌اکنون پروژه‌ی شما بر روی دامنه شما به همراه https قابل دسترسی است.هرجا که به مشکل خوردید یا سوالی داشتید، می‌تونید زیر همین پست یا در توییتر من بپرسید.</description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>نوید بقولی‌زاده</author>
                <pubDate>Sun, 21 Feb 2021 14:10:41 +0330</pubDate>
            </item>
                    <item>
                <title>یه هوک جذاب ! (useRedux) ?</title>
                <link>https://virgool.io/iran-react-community/%DB%8C%D9%87-%D9%87%D9%88%DA%A9-%D8%AC%D8%B0%D8%A7%D8%A8-useredux-qezbd5hwxhte</link>
                <description>چی؟! useRedux؟!! ?بله.الان میخوام یه تولز خفن بهت یادم که کارهای مربوط به ریداکست رو مثل باقلوا انجام بده.فقط اول باید این چندتا چیز رو بلد باشی تا بتونی متوجه بشی که من چه کردم:هوک (Hook)ریداکس (Redux)الان نمیخوام  وارد هوک و ریداکس بشم چون پایه این مقاله بر اساس بلد بودن این دو هست.تو همین سایت ویرگول دوستان بسیاری درباره هوک کاملا توضیح دادن که پیشنهاد میکنم اول اونا رو مطالعه کنی بعد بیای ادامه راه و با هم بریم ?بریم useRedux رو بسازیم ☺️اول از همه برای اینکه این پروژتون یه مقدار سر و سامون بگیر بیاین تو روت پروژه یه فولدر hooks بسازید و تمام هوک هاتون رو توش تعریف کنید.حالا بیاین تو همون فولدری که ساختین (hooks) یه فایل به نام useRedux.ts بسازید (من برای اینکه کارتون راحت تر بشه تو استفاده کردن ازش اومدم از تایپ اسکریپت استفاده کردم که بهمون پیشنهاد بده)حالا بیاین تو فایلی که ساختین هوکتون رو درست کنید:خب بزارید درباره کانتکست این useRedux عزیزمون یه توضیحی بهتون بدم که دقیقا باید چه کاری رو برامون بکنه.کله بدبختی ما سر اضافه کردن و یا ادیت کردن استیت‌هاست که باید الان تو قالب گلوبال باشه. برای همین اومدن redux و context و ... رو تعریف کردن. (تا اینجا اوکی؟)حالا ما با نوشتن یک هوک ساده میایم سه عمل اصلی (دریافت , ذخیره , ریست) رو به راحتی هندل میکنم.پس میایم سه تا تابع به نام‌ها  Get , Save و Reset تعریف میکنم و اون ها رو تو آبجکتی که هوکمون دار return میکنه , اضافه میکنیم.خب اول از اون که باید حتما react-redux و redux پروژتون کاملا اپدیت باشه تا هوک‌های ریداکس رو شامل بشه. بعد بیاید تو App.js پروژتون و موارد زیر رو ایمپورت کنید:import {createStore} from &#039;redux&#039;;
import {Provider} from &#039;react-redux&#039;;
import React, {useState} from &#039;react&#039;;
import Reducers from &#039;فایلی که توش کامباین ردیوسرز ریتر میشه&#039;بعدش به محض اینکه تابع App تعریف شده بود توش این کد رو اضافه کنید:const App = () =&gt; {
          const [store] = useState(createStore(Reducers));
...بعدشم که مشخص باید مثل قبلانا بیاین این استور رو به Provider پاس بدین و حتما هم Provider باید تگ اصلی اپتون باشه:خب تا الان کانفیگ ریداکسمون رو یه مقدار دستکاری کردیم برای اینکه بتونیم از هوک های ریداکس استفاده کنیم. حالا برمیگردیم به فایل useRedux خودمون که ادامه کار رو بنویسیم.الان ما برای تغییر دادن استیت‌هامون به یه dispatch نیاز داریم که باید بیایم اون رو از هوک useDispatch که react-redux بهمون میده دریافت کنیم.پس اول useDispatch رو از react-redux ایمپورت کنید بعد داخل و زیر فانکشن useRedux این کد رو برای گرفتن dispatch بنویسید:const useRedux = () =&gt; {      const dispatch = useDispatch();
...حالا ما dispatch رو داریم که خیلی راحت میتونیم باهاش استیت ها رو تغییر بدیم (برای تابع Save, Reset استفاده میشه)حالی بیاین یکی یکی تابع ها رو اوکیشون کنیم:اول بریم سراغ Get:بیاین useSelector رو هم از react-redux ایمپورت کنید تا بتونیم استیت‌هامون رو ازش دریافت کنیم.import {useDispatch, useSelector} from &#039;react-redux&#039;;حالا بیاین زیر همون جایی که useDispatch رو تعریف کردیم و این کد رو بنویسید:const useRedux = () =&gt; {      const dispatch = useDispatch();
      const states = useSelector((state: ReducersStates) =&gt; state) as ReducersStates;
...آقا فوحشم ندینا ? الان میگم ReducersStates چیه. یه لحظه صبرِلَ ??بابا من اومدم یه چندتا اینترفیس قبلا تعریف کردم که توش تمام تایپ های استیت هام هست. نگاه کنید:این تایپ های استیت های user ام هستاینم تایپ‌های استیت‌های اپم هستحالا اومدم یه اینترفیس تعریف کردم که یه آبجکت که استیت های app و user رو دار که با زدن . میتونید بهش دسترسی داشته باشید.فقط من اومدم هر کدوم از این اینترفیس هارو جداگونه تو فایل های مختلف تعریف کردم که مرتب تر باشه.قابل توجه دوستانی که هنوز تایپ اسکریپت بلد نیستند (این اینترفیس ها و تایپ ها هستند که موقع دولوپ در vsCode به شما ادامه کد رو پیشنهاد میدن). پس لطف کنید و سریع سوییچ کنید رو تایپ اسکریپت تا از شر دیباگ‌های وقت گیر راحت بشیدتو تمام ide ها این پیشنهاد ها میاد براتون (پس اگر وقتت برات با ارزش سوییچ کن رو تایپ اسکریپت)حالا داخل بدنه تابع Get امون کافیه states رو return کنیم تا تمام state هامون رو بتونیم بعد از فراخونی کردن تابع Get بگیریم.const Get = () =&gt; {return states}خب تابع Get دیگه اوکی شد. از این به بعد هم هر موقع خواستین از استیت هاتون استفاده کنید کافیه این کار رو بکنید:export const CustomButton = () =&gt; {
    const states = useRedux().Get()
...حالا بریم سر اصل کاری که Save:این بدنه تابع Save امون هست:const Save = (data: UserStates | AppStates, statesType: &#039;user&#039; | &#039;app&#039;) =&gt; {      switch (statesType) {            case &#039;app&#039;:                data = data as AppStates;                dispatch(appChangeData(data));                 break;           case &#039;user&#039;:                data = data as UserStates;                dispatch(userChangeData(data));                break;           }
};بچه‌ها با تجربه سریع گرفتن که چی شد ??دوستان عزیز. ببینید من کار شاخی نکردم به خدا.. اومدم گفتم که من کلا دوتا دسته استیت دارم (app,user) که میخوام هر موقع یه استیتی رو توشون اپدیت کنم باید بیام بگم که کدوم استیت هست و تو کدوم دسته قرار داره. (همین!)یه نکته: اون کلمه as کارش این هست که تایپ ها رو تبدیل میکنه به هم پس درگیر اون نشید.و اینکه appChangeData و userChangeData هر دو اکشن های من هستند:appChangeDatauserChangeDataبزارید یکی از ردیوسرهام رو هم نشون بدم:میاد پراپرتی که تو payload یا value اکشن هست رو اسپرینگ میکنه تو استیت نهایی ردیوسرالان میخوام به عونان مثال بیام استیت connection رو تو دسته app اپدیت کنم (یه نگاه به عکس‌های اینترفیس ها بندازید استیتام هست). برای این کار کافیه بیام بنویسم:از زیبایی های تایپ اسکریپت const {Save} = useRedux()Save({connection: true}, &#039;app&#039;)و تمام!راحت تر از این مگه میشه اصلا؟!??کانفیگ اولش شاید یه مقدار زمان گیر باشه (البته بیشتر از ۱۵ دقیقه کار نمی‌بر) ولی موقع استفاده کردن خیلی راحت تر.حالا هم بریم سر اخرین تابع که همون Reset:const Reset = (statesType: &#039;app&#039; | &#039;user&#039;) =&gt; {      switch (statesType) {          case &#039;app&#039;:          dispatch(appResetData());          break;      case &#039;user&#039;:          dispatch(userResetData());          break;      }};این تابع هم که کارش ریست کردن استیت‌ها به مقدار اولیشون هست.اکشنش ایناین هم ردیوسرم هست که اکشنش USER_RESET_DATA هست که میاد همون استیت ها رو با مقدار اولیه return  میکنهتبریک میگم ? ?اقا بالاخره تموم شد و میتونید از این به بعد یه نفس راحت از دست ریداکس بکشید ?بیاین یه بار دیگه استفاده کردن ازش رو ببینیم ?:const {Get, Save, Reset} = useRedux();const states = Get() یا Get().app //گرفتن استیت ها
Save({connection: true}, &#039;app&#039;) //ذخیره یا اپدیت کردن
Reset(&#039;app&#039;) //ریست کردن استیت appدوستان ممنونم از اینکه مقاله من رو خوندین. من سعی کردم خیلی در فضای خودمونی و جذاب بهتون توضیح بدم و امیدوارم که تونست باشم کارتون رو راحت تر کرده باشم.لطف کنید حتما نظر بدین چون این اولین مقاله من در ویرگول هست و اگر بازخورد ها خوب باشه بازم هم ادامه خواهم داد.من تا میتونم دارم سعی میکنم که این useRedux رو بهینه ترش کنم. لطفا تو این کار من رو یاری کنید و اگر چیزی به ذهنتون اومد حتما تو نظرات یا به ای دی تلگرامم ارسال کنید: تلگرام: @nodes2684منتظر بازگشت سلطان باشید ??</description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>Hosein Moayedi</author>
                <pubDate>Sun, 30 Aug 2020 16:33:30 +0430</pubDate>
            </item>
                    <item>
                <title>تقویم شمسی ری اكت و اعتبارسنجی فرم</title>
                <link>https://virgool.io/iran-react-community/%D8%AA%D9%82%D9%88%D9%8A%D9%85-%D8%B4%D9%85%D8%B3%DB%8C-%D8%B1%D9%8A%D8%A7%D9%83%D8%AA-%D9%88-%D8%A7%D8%B9%D8%AA%D8%A8%D8%A7%D8%B1%D8%B3%D9%86%D8%AC%D9%8A-%D9%81%D8%B1%D9%85-fo8vlft8stgi</link>
                <description>سلام دوستانحدود چند روزی در گیر این بودم که چطور در ریاکت از تقویم شمسی استفاده کنم، راه حل ساده بود اما مشکل از اون جایی به وجود اومد که نیاز بود فیلد اجباری باشه.خوب راه حل ساده تقویم شمسی ، استفاده از Date Picker هست که خیلی از پکیج هارو تست کردم اما... قبل از این مبحث بزارید فیلد اجباری رو بگم.برای فیلد اجباری از react hook form استفاده کردم که واقعا عالی هست.روش استفاده به شکل زیر هست?import React , {useState , useEffect} from &#039;react&#039;;
import { useForm } from &amp;quotreact-hook-form&amp;quot

function Main(){
const { register , handleSubmit, errors } = useForm();
const errorsMassage = &lt;p className=&amp;quoterrors-massage&amp;quot&gt;اطلاعات را وارد نمایید&lt;/p&gt;
const  = data =&gt; {
const token = localStorage.getItem(&amp;quottoken&amp;quot)
addSkillData({
newItem:  {
&amp;quottitle&amp;quot : data.title,
&amp;quotexpense&amp;quot : data.expense,
&amp;quotstartDate&amp;quot : data.startDate,
},
config : {
headers : {
&amp;quotAuthorization&amp;quot : `Bearer ${token}
}}})};

return (&lt;&gt;
&lt;form ={handleSubmit()}&gt;
&lt;div className=&amp;quotform-group col-lg-4 col-md-12&amp;quot&gt;
&lt;label className=&amp;quotmr-1&amp;quot htmlFor=&amp;quot&amp;quot&gt;عنوان&lt;/label&gt;
&lt;input className=&amp;quotform-control&amp;quot id=&amp;quotaddskill-title&amp;quot
name=&amp;quottitle&amp;quot ref={register({ required: true })} /&gt;
{errors.title &amp;&amp; errorsMassage}
&lt;/div&gt;
&lt;div className=&amp;quotform-group col-lg-4 col-md-12&amp;quot&gt;
&lt;label className=&amp;quotmr-1&amp;quot htmlFor=&amp;quot&amp;quot&gt;میزان هزینه&lt;/label&gt;
&lt;input type=&amp;quottext&amp;quot className=&amp;quotform-control&amp;quot id=&amp;quotaddskill-expense&amp;quot
name=&amp;quotexpense&amp;quot ref={register({ required: true })} /&gt;
{errors.expense &amp;&amp; errorsMassage}
&lt;/div&gt;
&lt;div className=&amp;quotform-group col-lg-4 col-md-12&amp;quot&gt;
&lt;label className=&amp;quotmr-1&amp;quot htmlFor=&amp;quot&amp;quot&gt;تاریخ شروع&lt;/label&gt;
&lt;input type=&amp;quotdate&amp;quot className=&amp;quotform-control&amp;quot id=&amp;quotaddskill-start-date&amp;quot
name=&amp;quotstartDate&amp;quot ref={register({ required: true })} /&gt;
{errors.startDate &amp;&amp; errorsMassage}
&lt;/div&gt;
&lt;input className=&amp;quotbtn btn-primary btn-user btn-block&amp;quot type=&amp;quotsubmit&amp;quot value=&amp;quotثبت&amp;quot /&gt;
&lt;/form&gt;
&lt;/&gt;
)}خوب در بالا همان طور که می‌بینید در هر input از اتریبیوتی به نام ref استفاده کرده تا مقادیر را علاوه بر ارسال به استیت، اعتبار سنجی هم کنه و در نهایت مقادیر در تابع  که به handleSubmit در تگ اصلی فرم در دسترس ما هستند.حالا من در همین شرایط از دیتا پیکر استفاده کردم مثل زیر ?import React , {useState , useEffect} from &#039;react&#039;;
import { useForm } from &amp;quotreact-hook-form&amp;quot
import { DatePicker } from &amp;quotdavood-react-persian-datepicker&amp;quot

function Main(){
const { register , handleSubmit, errors } = useForm();
const errorsMassage = &lt;p className=&amp;quoterrors-massage&amp;quot&gt;اطلاعات را وارد نمایید&lt;/p&gt;
const  = data =&gt; {
const token = localStorage.getItem(&amp;quottoken&amp;quot)
addSkillData({
newItem:  {
&amp;quottitle&amp;quot : data.title,
&amp;quotexpense&amp;quot : data.expense,
&amp;quotstartDate&amp;quot : data.startDate,
},
config : {
headers : {
&amp;quotAuthorization&amp;quot : `Bearer ${token}`
}
}})};

return (&lt;&gt;
&lt;form ={handleSubmit()}&gt;
&lt;div className=&amp;quotform-group col-lg-4 col-md-12&amp;quot&gt;
&lt;label className=&amp;quotmr-1&amp;quot htmlFor=&amp;quot&amp;quot&gt;عنوان&lt;/label&gt;
&lt;input className=&amp;quotform-control&amp;quot id=&amp;quotaddskill-title&amp;quot
name=&amp;quottitle&amp;quot ref={register({ required: true })} /&gt;
{errors.title &amp;&amp; errorsMassage}
&lt;/div&gt;
&lt;div className=&amp;quotform-group col-lg-4 col-md-12&amp;quot&gt;
&lt;label className=&amp;quotmr-1&amp;quot htmlFor=&amp;quot&amp;quot&gt;میزان هزینه&lt;/label&gt;
&lt;input type=&amp;quottext&amp;quot className=&amp;quotform-control&amp;quot id=&amp;quotaddskill-expense&amp;quot
name=&amp;quotexpense&amp;quot ref={register({ required: true })} /&gt;
{errors.expense &amp;&amp; errorsMassage}
&lt;/div&gt;
&lt;div className=&amp;quotform-group col-lg-4 col-md-12&amp;quot&gt;
&lt;label className=&amp;quotmr-1&amp;quot htmlFor=&amp;quot&amp;quot&gt;تاریخ شروع&lt;/label&gt;
&lt;input type=&amp;quothidden&amp;quot className=&amp;quotform-control&amp;quot id=&amp;quotaddskill-start-date&amp;quot
name=&amp;quotstartDate&amp;quot ref={register({ required: true })} /&gt;
&lt;DatePicker /&gt;
{errors.startDate &amp;&amp; errorsMassage}
&lt;/div&gt;
&lt;input className=&amp;quotbtn btn-primary btn-user btn-block&amp;quot type=&amp;quotsubmit&amp;quot value=&amp;quotثبت&amp;quot /&gt;
&lt;/form&gt;
&lt;/&gt;
)}همان طور که مشخص هست ، سعی داشتم input تاریخ میلادی را hidden کنم و تاریخ خروجی DatePicker  را به value اینپوت پاس بدم که موفق هم شدم ( بدون استفاده از queryselector ) اما دیگه ref اجرا نمیشد و ارور عمل نمیکرد.اینجا بود که یکم کلافه شدم و با پرس و جو چند روزه ای که داشتم به یک جواب بسیار شیک رسیدم.ما در react-hook-form یک متد داریم به نام Controller که اگر در جایی امکان استفاده مستقیم خود input نبود یا ref در دسترس نبود میشه ازش استفاده کرد.روش استفاده به شکل زیر هست ?import React , {useState , useEffect} from &#039;react&#039;;
import { useForm , Controller } from &amp;quotreact-hook-form&amp;quot
import { DatePicker } from &amp;quotdavood-react-persian-datepicker&amp;quot

function Main(){
const { register , handleSubmit, errors , control } = useForm();
const errorsMassage = &lt;p className=&amp;quoterrors-massage&amp;quot&gt;اطلاعات را وارد نمایید&lt;/p&gt;
const  = data =&gt; {
const token = localStorage.getItem(&amp;quottoken&amp;quot)
let date = moment(data.startDate).format(&#039;YYYY/M/D&#039;)
addSkillData({
newItem:  {
&amp;quottitle&amp;quot : data.title,
&amp;quotexpense&amp;quot : data.expense,
&amp;quotstartDate&amp;quot : date,
},
config : {
headers : {
&amp;quotAuthorization&amp;quot : `Bearer ${token}`
}
}})};

return (&lt;&gt;
&lt;form ={handleSubmit()}&gt;
&lt;div className=&amp;quotform-group col-lg-4 col-md-12&amp;quot&gt;
&lt;label className=&amp;quotmr-1&amp;quot htmlFor=&amp;quot&amp;quot&gt;عنوان&lt;/label&gt;
&lt;input className=&amp;quotform-control&amp;quot id=&amp;quotaddskill-title&amp;quot
name=&amp;quottitle&amp;quot ref={register({ required: true })} /&gt;
{errors.title &amp;&amp; errorsMassage}
&lt;/div&gt;
&lt;div className=&amp;quotform-group col-lg-4 col-md-12&amp;quot&gt;
&lt;label className=&amp;quotmr-1&amp;quot htmlFor=&amp;quot&amp;quot&gt;میزان هزینه&lt;/label&gt;
&lt;input type=&amp;quottext&amp;quot className=&amp;quotform-control&amp;quot id=&amp;quotaddskill-expense&amp;quot
name=&amp;quotexpense&amp;quot ref={register({ required: true })} /&gt;
{errors.expense &amp;&amp; errorsMassage}
&lt;/div&gt;
&lt;div className=&amp;quotform-group col-lg-4 col-md-12&amp;quot&gt;
&lt;label className=&amp;quotmr-1&amp;quot htmlFor=&amp;quot&amp;quot&gt;تاریخ شروع&lt;/label&gt;
&lt;Controller
control={control}
name=&amp;quotstartDate&amp;quot
rules={{ required: true }}
defaultValue={moment(skillEditingData.startDate)}
render={({on4Change, on5Blur, va6lue }) =&gt; (
&lt;DatePicker
calendarStyles={styles}
inputFormat=&amp;quotjYYYY/jM/jD&amp;quot
v1alue={va4lue}
o2nBlur={on6Blur}
o3nChange={on5Change}
/&gt;
)}
/&gt;
{errors.startDate &amp;&amp; errorsMassage}
&lt;/div&gt;
&lt;input className=&amp;quotbtn btn-primary btn-user btn-block&amp;quot type=&amp;quotsubmit&amp;quot value=&amp;quotثبت&amp;quot /&gt;
&lt;/form&gt;
&lt;/&gt;
)}در Controller به جای ref آمده از rules استفاده کرده و گفته در render هر آنچه دوست داری رندر کن فقط onChang1e, onBlu2r, valu3e هارو پاس بده بهش و تمام. ( اعداد به خاطر اينه كه ويرگول كاراكتر هاي مشابه رو حذف ميكنه ،‌شما حتما پاک کنید )و در آخر منابع رو هم بررسی کنیم:برای DatePicker از https://www.npmjs.com/package/davood-react-persian-datepicker استفاده کردم البته آن زمانی که داشتم پکیج های مختلف رو تست میکردم تمرکزم روی ref بود ، احتمال زیاد با این خاصیت Controller راحت میشه از هر پکیج دیگه ای استفاده کرد.برای Controller هم https://react-hook-form.com/api/#Controller را بررسی کنید.و در نهایت خروجی که DatePicker بهتون میده رو به https://github.com/jalaali/moment-jalaali بدید به شکل زیر ?let date = moment(data.startDate).format(&#039;YYYY/M/D&#039;) //میلادی
let dateJalali = moment(data.startDate).format(&#039;jYYYY/jM/jD&#039;) //شمسیامیدوارم مورد استفاده قرار گرفته باشهسوالی داشتید حتما بپرسید</description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>محمدسجاد دباغ</author>
                <pubDate>Mon, 27 Jul 2020 14:22:09 +0430</pubDate>
            </item>
                    <item>
                <title>حذف Rerender های اضافی در کامپوننت های React</title>
                <link>https://virgool.io/iran-react-community/%D8%AD%D8%B0%D9%81-rerender-%D9%87%D8%A7%DB%8C-%D8%A7%D8%B6%D8%A7%D9%81%DB%8C-%D8%AF%D8%B1-%DA%A9%D8%A7%D9%85%D9%BE%D9%88%D9%86%D9%86%D8%AA-%D9%87%D8%A7%DB%8C-react-o66d7yeoubni</link>
                <description>من با Angular.js شروع کردم (version 1). اصلا اون موقع هنوز ری اکتی با این هیبت وجود نداشت. ورژن های جدید angular هم زاده نشده بودن. Vue و امثالهم هم بعدها به بازار اضافه شدن. بنابراین، اون سالها شاخ ترین Framework برای Frontend همین angular ورژن یک بود. توسط گوگل هم پشتیبانی شده بود و خیال همه راحت که بهترین انتخاب ممکن هست. تنها رقبایی که براش وجود داشتن، Ember و Backbone بودن. این دو تا هم طرفدارای خاص خودشون رو داشتن ولی واقعا در حد Angular نبود. یکی از مشکلاتی که خود من با Angular داشتم، این بود که وقتی یه پروژه ی با Scale بالا رو باهاش میزدی، از یه جایی به بعد، کندی رو میدیدی. اصلا مشخص بود دیگه داره به مرحله ی زایش میرسه. یه مدت که گذشت، React اومد تو بورس. نقطه ی قوتش هم چیزی نبود جز Virtual Dom. آقا ما که با این مشکلات Angular آشنا بودیم، ندیده و نشناخته عاشق Virtual DOM و ری اکت شدیم. همین موقع ها هم بود که Angular V2 به بالا وارد شدن. اما به خاطر وجود نداشتن این ویژگی، واقعا چشم و دل ما براش نرفت. حتی تا وقتی Angular V4 معرفی نشد من در مورد سینتکس هاشم نخوندم. اما بنا بر تقدیر، ما اول با Angular نسل جدید شروع کردیم. یه Framework کامل و غول که همه چیزی داشت. اصلا هرکاری بخوای باهاش بکنی میشه. منتهی یکمی زیادی کامله و واقعا برای اپلیکیشن هایی که برای یه بیزنس با تعداد مشتری های بالا و اپلیکیشن large Scale هست، خیلی انتخاب جالبی نیست. چون بحث اصلی تاپیک نیست زیاد وارد جزییات نمیشم، همینقد بگم من با Angular و React اپ های خیلی بزرگی زدم، پس بعد از یه تجربه ی بزرگ دارم همچین جمله ای میگم. بگذریم!با وجود React و قابلیت مهمش، دیگه با خیال راحت میشد رفت سراغ پیاده سازی. خب وقتی ندیده و نشناخته، میری سراغ یه اپلیکیشن Large Scale و خیالت راحته که قراره یه Performance عالی تحویل بدی، یهویی میرسی به یه نقطه ای که میبینی کندترین اپلیکیشن ممکن رو ساختی! حالا ببینیم چرا؟این قابلیت (Virtual DOM) برای خودش یه سری قواعد و قوانین داره. به هر حال مقایسه هایی که بین آپدیت های مختلف صورت میده، همه شون به یک شکل نیست. یه جاهایی این مقایسه ها روی Reference صورت میگیره، یه جاهایی روی Value. ممکنه شما به Debugger تون نگاه کنید و ببینید، آپدیتی روی Value ها ندارید ولی مثل ضربان قلب گنجشنک، کامپوننتت داره update میشه. این آپدیت شدن ها، هرکدوم ممکنه دلایل خاص خودش رو داشته باشه، اما من امروز میخوام در مورد Memo کردن یه کامپوننت صحبت کنم. یکی از قابلیت هایی که با هوک ها معرفی شد، useMemo هست. این قابلیت به شما این امکان رو میده که کامپوننتتون رو داخل یه wrapper به نام React.memo رپ کنید، یه فانکشن کاستوم بهش بدید و براش تعیین کنید که در چه شرایطی میخواین کامپوننتتون آپدیت بشه. بریم ببینیم چجوری:اینجا شما یه نتیجه از Profiler در کروم میبینید. یکی از صفحات اپلیکیشن من هست که وقتی درشون اکشن هایی رو انجام میدید، این مقدار ریرندر و time consuming وجود دارهکامپوننت Header کارت من، بیشترین میزان Rerender رو داشته در حالی که در این تستی که من گرفتم، هیچ کاری باهاش نداشتم. یه اکشنی رو روی یه کامپوننت دیگه توی Page انجام دادم و چون فقط یه state در Parent این کامپوننت ست شد، و کامپوننت پدر، Rerender شد، این کامپوننت و تمام بچه هاش، یه بار دیگه رندر شدن. خب دلیلش چیه؟یکی از دلایلی که وجود داره اینه که ممکنه رفرنس آبجکت یا آرایه ای که به این کامپوننت پاس دادین، عوض شده باشه. برای همین میتونیم از React.memo توی این کامپوننت استفاده کنیم. به این صورت :function HeaderCard(props){
     ...
     return &lt;div&gt;
                  ...
             &lt;/div&gt;
}function areEqual(prevProps, currProps) {
  return prevProps.title === currProps.title
}export default React.memo(HeaderCard, areEqual)توی این wrapper ای که برای کامپوننت میزارم، یه فانکشن پاس میدم به اسم areEqual. این تابع، بعد از هر بار درخواست رندر جدیدی که میاد، یه بار کال میشه و مقدار قبلی Prop ها و مقدار فعلی رو در اختیارتون میزاره. شما میتونید در بدنه ی این تابع، یه سری شروط بنویسید که فقط در صورت true شدن اون شرط ها، کاپوننتتون آپدیت و در نهایت Rerender بشه. مثلا در این کامپوننت من میخوام فقط وقتی title آپدیت شد، Rerender صورت بگیره. برای همین شرطم به این شکله که تا زمانی که مقادیر قبل و بعد title با هم برابر هستن، یعنی Prop ها با هم برابرن و نباید ریرندر انجام بشه.این از مرحله ی اول. اگر کالبکی به کامپوننت خودتون پاس نداده باشین، همین کار کافیه و همین عمل باعث میشه که ریرندر اضافی از دوش کامپوننت برداشته بشه.اما خیلی از دفعات هست که شما به instance کامپوننتون، یه کالبک پاس میدید. React.memo فقط میتونه جلوی آپدیت های بی مورد Prop ها رو بگیره. اما با هر بار آپدیت شدن Parent یه instance جدید از کالبکی که به کامپوننت دادید ساخته میشه و باعث کال شدن مجدد کامپوننت میشه. برای حل این مشکل، این بار باید از useCallback استفاده کنید:&lt;HeaderCard
         ...
        onFaveClick={memoizedAddToFave}
        Comment={memoizedClickComment}
        Information={memoizedClickInformation}
/&gt;اینجا، بعد از پاس دادن Prop ها به کامپوننت، سعی میکنیم، Function ها رو هم Memoize کنیم. حالا ببنیم منظور از این چیه؟const memoizedClickInformation = useCallback((x) =&gt; {
  callFunctionA(x)
}, [y])ما میخوایم وقتی داخل کامپوننت، تابع Information کال شد، تابع callFunctionA رو با ورودی x که از کامپوننت بهش داده میشه، کال کنیم. این کار با استفاده از useCallback به شکل بالا انجام میشه. اون مقداری که در آرایه به عنوان آرگومان دوم به useCallback پاس داده شده، یعنی [y] به این معنی هست که این تابع من، به مقدار y ، وابسته است یا اصطلاحا dependency داره. پس هر وقت مقدار y آپدیت شد، این کالبک هم باید آپدیت بشه و یه instance جدید ازش ساخته بشه. مثلا فرض کنید x یکی از attr های آبجکت y هست. اگر این dependency رو انجام ندید، ممکنه مقدار x در آبجکت y تغییر کنه اما وقتی کالبک صدا زده میشه، مقدار قبلی x رو دریافت کنید.خب حالا ببینیم با این کار، نتیجه چه تغییری میکنه:میبینید که در شرایط مشابه، نسب به حالت قبل، تمامی ریرندرهای اضافی حذف شد و به صفر رسید.در پایان اینو بگم که ، این کار در حالت کلی توصیه نمیشه. چون باعث Memory usage زیادی میشه و فقط در مواقع Critical باید ازش استفاده بشه. از طرفی اگر Component Composition درستی وجود داشته باشه و معماری اپتون از اول درست باشه، این اتفاق نمی افته. اما یه زمانایی هم اجتناب ناپذیره. موفق باشید.</description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>محمدجواد سیدی</author>
                <pubDate>Fri, 12 Jun 2020 19:48:09 +0430</pubDate>
            </item>
                    <item>
                <title>کی باید به setState تابع پاس بدیم؟</title>
                <link>https://virgool.io/iran-react-community/when-to-pass-function-to-use-state-erserk2a0x8k</link>
                <description>تابع setState رو توی ری‌اکت به دو شکل میتونیم استفاده کنیم.۱- با پاس دادن مقدار، و  ۲- با پاس دادن تابع.تو حالت اول مقداری که پاس میدیم جایگزین مقدار قبلی استیت میشه (توی class component مقدار باید object باشه و با object قبلی merge میشه) و تو حالت دوم، ری‌اکت آخرین مقدار state رو بعنوان ورودی به تابعی که بهش دادیم میده و از مقدار خروجی تابع بعنوان مقدار برای setState کردن، مشابه حالت اول، استفاده می‌کنهحالا سوالی که پیش میاد اینه:چه زمانی ما نیاز داریم که به setState تابع پاس بدیم؟ و چرا؟بعنوان یه حکم همیشگی، میشه گفت که هروقت مقدار جدید state به مقدار قبل از خودش وابسته بود، باید از function برای setState استفاده کنیم. ینی چی؟ به این مثال دقت کنید: setValue(value + 1);توی این مثال مقدار جدید value واضحا به مقدار قبلی خودش بستگی داره. ما در حال حاضر یه مقداری رو بعنوان value داریم که مثلا برابر ۱ هست و با استفاده از اون می‌خوایم value جدید که ۲ میشه رو بسازیم. اینجور مواقع بهتره که از function بجای پاس دادن مستقیم مقدار استفاده کنیم:setValue(value =&gt; value + 1);&quot; /&gt; value + 1);&quot; /&gt;setValue(value =&gt; value + 1);اینجا ما بجای اینکه مستقیم از value استفاده کنیم، یه تابع به setValue پاس دادیم. ری‌اکت آخرین مقدار value رو به تابع ما پاس میده و مقداری که return میشه رو داخل استیت ست می‌کنه.برای این حکم همیشگی رو رعایت میکنیم، که اگر ۱۰۰٪ مواقع کدمون رو اینجوری بنویسیم، می‌تونیم مطمئن باشیم که هیچوقت هیچ مشکلی پیش نمیاد. هرچند که فقط ۲۰٪ مواقع مشکل‌ساز باشن.این ۲۰٪ مواقع کی‌ها هستند؟این ۲۰٪ مواقع دردسرساز، که ما رو مجبور به استفاده از function برای setState می‌کنند، به دو دسته تقسیم میشن.دسته اول:همه ما با نکته زیر توی جاوااسکریپت آشناییم. ولی انگار وقتی وارد ری‌اکت میشیم فراموشش میکنیم.مفهوم closure در جاوا‌اسکریپتما این رو میدونیم و مطمعنیم که firstLogger رو هروقت صدا بزنیم مقدار 0 رو داخل کنسول چاپ می‌کنه. و مهم نیست که بعد از دفعه اول، تابع getLogger رو با مقادیر دیگه‌ای هم صدا زده باشیم یا نه. چرا؟ چون تابع firstLogger مقدار 0 رو داخل closure خودش ذخیره کرده. حالا مثال زیر رو ببینید:مفهوم closure در function componentتوی این مثال، ما دوتا دکمه روی صفحه داریم که کلیک بر روی یکیشون مقدار a رو لاگ میگیره و کلیک بر روی اونیکی مقدار a رو به 1 تغییر میده. حالا اگه اول روی دکمه Log کلیک کنیم، میبینیم که عدد 0 لاگ گرفته میشه. ولی اگه روی دکمه Inc و سپس Log کلیک کنیم، انتظار داریم عدد 1 لاگ گرفته بشه اما چیزی که میبینیم همون عدد 0 هست. چرا؟دلیلش ساده‌اس. ما از useCallback استفاده کردیم و بعنوان dependencies array بهش یه آرایه خالی دادیم (اگر نمی‌دونید dependencies array چیه اینجا رو بخونید). درواقع با پاس دادن dependencies array خالی به useCallback، داریم به ری‌اکت میگیم که فرقی نمی‌کنه که چه اتفاقی میافته، تابع logger باید همیشه همون تابعی که دفعه اول ساخته شده بمونه. ینی همون تابع firstLogger توی مثال قبلی. توی مثال قبلی اینکه دوباره تابع getLogger رو با مقدار جدید صدا میزدیم، باعث میشد که مقداری که firstLogger لاگ میگیره عوض بشه؟ نه. پس توی این مثال هم اینکه کامپوننت رو با استیت جدید رندر بکنیم، باعث نمیشه تابعی که دفعه اول ساخته شد مقدار جدیدی رو لاگ بگیره. و useCallback داره باعث میشه که همیشه همون تابع اولیه برگرده. درست کردنش راحته:رفع مشکل با اضافه کردن متغیرهای مورد استفاده در closure به dependency arrayاینجوری میتونیم بگیم که هروقت مقدار a عوض شد، useCallback تابع جدیدی که ساخته میشه رو بهمون پس بده. یعنی انگار که توی مثال جاوااسکریپتی بالا، همیشه آخرین مقدار برگشتی از getLogger رو داشته باشیم.خب برگردیم سر بحث خودمون. بیاید فرض کنیم بجای تابع logger همچین چیزی داریم:مشکل closure در function componentاین کد درست کار نمی‌کنه. توی مثال قبل یادتونه که تابع logger همیشه 0 رو لاگ میگرفت؟ توی این مثال هم، این تابع مقدار count = 0 رو حفظ کرده و هر دفعه که increment رو صدا میزنیم، انگار که داریم میگیم:دلیل بوجود آمدن مشکل closure در function componentینی همیشه داریم مقدار 1 رو بعنوان count ست می‌کنیم. برا همین دکمه Inc بعد از بار اول که مقدار count رو 1 می‌کنه، بنظر میرسه که دیگه کار نمی‌کنه.راه حل چیه؟ ساده‌اس. دوتا کار میشه کرد، یکی اینکه مثل حالت قبل، به ری‌اکت بگیم که هردفعه یه تابع جدید برای increment بسازه:حل مشکل closure با اضافه کردن count به dependency arrayاینجوری خیالمون راحته که هردفعه که کامپوننت با مقدار جدیدی برای count دوباره رندر میشه، یه تابع جدید ساخته میشه و این تابع جدید بعنوان  روی button ست میشه.و راه حل دوم اینه که بجای خوندن count از closure، به ری‌اکت بگیم خودش آخرین مقدار count رو بهمون بده:حل مشکل closure با پاس دادن function به تابع setStateاینجوری فقط یک بار تابع increment رو میسازیم ولی هربار که صداش میزنیم، آخرین مقدار count رو میگیره و یک واحد بهش اضافه می‌کنه.البته ترجیح من برای ساخت همچین تابعی اینه:(درسته که وقتی از useCallback استفاده نمی‌کنیم خیالمون راحته که همیشه آخرین مقدار count رو داخل closure داریم، اما قانون 80/20 یادتون نره و از function استفاده کنید) دسته دوم:اگر مورد بالا رو توی function component ها رعایت کنید، خودکار درمقابل دسته دوم هم مقاوم شدید. برای همین این دسته رو برای class component ها بررسی میکنیم.فرض کنید همچین کامپوننتی داریم: ?کلاس کامپوننت خودکار همه چیز رو پیچیده و طولانی می‌کنهاین کامپوننت قراره در وهله اول، یه آرایه از userها رندر کنه. یه prop به اسم shouldTrackCount هم میگیره که اگه true باشه تعداد userها رو هم داخل state نگه می‌داره (بچه‌های تو خونه قول بدید این کار رو نکنید) (فقط برای آموزش) (Don&#x27;t do this at home) (بجاش همون this.state.users.length رو داخل رندر استفاده کنید)قسمت هیجان انگیز ماجرا توی تابع addUser اتفاق میافته. تو این تابع ۲ تا setState داریم. اولی یه یوزر جدید به آرایه یوزرها اضافه می‌کنه، و دومین setState تعداد جدید یوزرهارو حساب می‌کنه و setState می‌کنه.اما این تابع درست کار نمی‌کنه. چرا؟ بخاطر batching.درواقع ری‌اکت setStateها رو بصورت sync انجام نمیده. یعنی چی؟ اگه تابع addUser رو به این شکل بازنویسی کنیم:اگر بلافاصله بعد از setState سعی کنیم که مقدار state رو لاگ بگیریم متوجه میشیم که تغییر نکرده.میبینید که هیچوقت user ای که اخیرا به state اضافه شده توی log دیده نمیشه. چرا؟ چون ری‌اکت setState رو همون لحظه انجام نمیده. درواقع با صدا زدن setState، ما ری‌اکت رو از تغییر باخبر می‌کنیم. اما تصمیم اینکه کی این تغییر انجام بشه با ری‌اکته و ری‌اکت معمولا ترجیح میده که بعد از تموم شدن تابع تغییرات رو اعمال کنه. چرا؟ چون اگه همون لحظه این‌کار رو بکنه، مجبوره یه دور درخت رو با استیت جدید رندر کنه و بعد اگه تو خط پایین یه setState دیگه داشته باشیم، مجبور میشه دوباره کل رندر کردن درخت رو تکرار کنه. برا همین صبر می‌کنه تا اجرای تابع تموم بشه، بعد همه تغییرات رو همزمان انجام میده.تو مثال addUser اگر فرض کنیم که داریم:بیاید روی object هایی که به setState پاس میدیم اسم بذاریمکاری که ری‌اکت درنهایت انجام میده شبیه به اینه:ری‌اکت setState های مارو تبدیل به همچین چیزی می‌کنهکه معادله با:شکل باز شده نتیجه setState های ماو به وضوح میتونیم ببینیم که this.state.users هنوز به مقدار قبلی آرایه users اشاره می‌کنه، چرا که درحال اجرای setState هستیم و هنوز تغییر استیت انجام نشده و درنتیجه length آرایه users هم همیشه مقدار قدیمی رو نشون میده.و راه حل این مشکل بازهم مثل همیشه استفاده از function برای setState عه. اینجوری به ری‌اکت میگیم که برای حساب کردن count به آخرین مقدار state نیاز داریم و ری‌اکت هم این مقدار رو بعنوان ورودی تابعمون بهمون میده.حل مشکل obsolete state با پاس دادن function به setStateوالسلام.(نکته اضافی)شاید متوجه شده باشید که نکته دوم، ینی batch کردن setState ها، همیشه اتفاق نمیافته. دلیلش اینه که ری‌اکت درحال حاضر یسری محدودیت‌ها برای انجام دادن این‌کار داره و فقط setState‌های داخل تابع‌هایی رو batch می‌کنه که توسط ری‌اکت فراخوانی میشن. بعنوان مثال تابع  تابعیه که ما به ری‌اکت میدیم و ری‌اکت هروقت که برروی المنت کلیک بشه صداش میزنه. و یا تابع componentDidMount تابعیه که توسط ری‌اکت صدا زده میشه و درنتیجه همه setStateهای داخلش باهمدیگه batch میشن.اما اگه کدی مثل شکل زیر داشته باشیم:ری‌اکت فقط setState هایی که توی تابع‌هایی که توسط ری‌اکت اجرا میشن رخ داده‌اند رو batch می‌کنهمتوجه میشیم که این دو setState بجای اینکه باهمدیگه batch بشن و منجر به ۱ رندر بشن، جدا جدا اعمال میشن و درخت ری‌اکت ۲ بار رندر میشه. دلیلش اینه که باوجود اینکه تابع componentDidMount توسط ری‌اکت صدا زده میشه، ولی تابع داخل then بصورت async اجرا میشه و در زمانی در آینده، توسط خود انجین جاوااسکریپت (و توسط Promise) صدا زده میشه. بنابراین کنترلش دست ری‌اکت نیست.درواقع کاری که ری‌اکت می‌کنه شبیه به اینه:کاری که ری‌اکت موقع صدا زدن تابع‌ها انجام میدهو این توی مثال بالا کار نمی‌کنه چون then بعد از صدا زده شدن endBatching صدا زده میشه و درنتیجه setState ها بصورت batch نشده اتفاق میافتن.راه حل چیه؟ درحال حاضر ری‌اکت یه تابع به اسم unstable_batchedUpdates اکسپورت می‌کنه که به ما اجازه میده خودمون دستی به ری‌اکت بگیم که setState هارو batch کنه.میتونیم با استفاده از unstable_batchedUpdates همه setState هامون رو batch کنیممیتونیم پیاده‌سازی این تابع رو معادل زیر فرض کنیم:پیاده‌سازی فرضی تابع unstable_batchedUpdatesاما توی استفاده ازش بشدت محتاط باشید. این تابع همونطور که از اسمش معلومه unstable هست و ممکنه تو هر ورژنی حذف بشه یا تغییر کنه و باعث بشه ارتقا دادن ری‌اکتتون سخت‌تر از چیزی بشه که باید باشه.ولی چرا ری‌اکت باید بخواد این تابع رو حذف کنه؟ دلیلش اینه که بعد از ریلیز شدن ورژن جدید ری‌اکت، با قابلیت concurrent mode (که درحال حاضر میتونید تحت فلگ experimental تستش کنید)، ری‌اکت اونقدری باهوش میشه که بتونه setState های دستی ما رو هم تشخیص بده و همرو با هم batch کنه و دیگه نیازی به این شکل استفاده کردن از unstable_batchedUpdates نخواهد بود.اما اینکه ری‌اکت چجوری میتونه setState های ما رو متوجه بشه؟ موضوع یه مقاله دیگه‌اس :)شاد و موفق باشید و امیدوارم از این به بعد توی setStateهاتون بیشتر از function استفاده کنید.دیگر مقالات من: https://vrgl.ir/gwLl7  https://vrgl.ir/2LzT9  https://vrgl.ir/WWPQ1 </description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>Eddie Cooro</author>
                <pubDate>Mon, 04 May 2020 00:06:04 +0430</pubDate>
            </item>
                    <item>
                <title>در سال 2020 از کدوم تکنولوژی کراس پلت فرم استفاده کنیم؟</title>
                <link>https://virgool.io/iran-react-community/%D8%AF%D8%B1-%D8%B3%D8%A7%D9%84-2020-%D8%A7%D8%B2-%DA%A9%D8%AF%D9%88%D9%85-%D8%AA%DA%A9%D9%86%D9%88%D9%84%D9%88%DA%98%DB%8C-%DA%A9%D8%B1%D8%A7%D8%B3-%D9%BE%D9%84%D8%AA-%D9%81%D8%B1%D9%85-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%DA%A9%D9%86%DB%8C%D9%85-fikgveycuysj</link>
                <description>React Native VS Ionic VS Flutterدر سال 2020 از کدوم تکنولوژی کراس پلت فرم استفاده کنیم؟در پروژه ای که اخیرا مشغول کار بر روی اون هستم باید برای توسعه کراس پلت فرم به روی وب ، اندروید و ای او اس با یک کد بیس، تکنولوژی رو انتخاب می کردم. خب انتخاب تکنولوژی همیشه اونقدر ها که به نظر میرسه ساده نیست. در حقیقت سخت ترین بخش تصمیم گیری برای انتخاب تکنولوژی برقرار تعادل بین منابعی که در اختیار دارید (اعم از: زمان، توانایی افراد تیم، کدهایی که قبلا نوشته شده و میشه استفاده مجدد کرد) و بهینه بودن قابلیت های تکنولوژی انتخابی هست.یعنی ممکنه همیشه بهترین تکنولوژی در یک حوزه، بهترین راه حل شما نباشه. خب در طی بررسی های انجام شده سه تا کاندید رو انتخاب کردم: Ionic- React Native - FlutterIONIC خوب بود ولی دو تا مسئله داشت اول اینکه خروجی تولید شده Native نبود. دوم اینکه علارغم ادعایی که داشت مبنی بر اینکه با فریم ورکهایی مثل React و Angular میشه باهاش کد زد، سربار یادگیری نسبتا زیادی داشت کارها رو به روش خودش انجام میداد نه به روش توصیه شده توسط هر یک از این فریم ورک و به این معنی زمان بیشتر برای یادگیری و احتمال وقوع مشکلات پیش بینی نشده بود. پسIONIC  رو کنار گذاشتیم.تکنولوژی بعدی فلاتر بود. خب Flutter از هر جهت ایده عال بنظر می رسید. خروجی موبایل و وب و دسکتاپ و تولید کد نیتیو برای هر پلت فرم با یک کد بیس. به لحاظ محبوبیت در حال رشد و نزدیک به React Native . بود و بر خلاف React Native که از معماری Bridge برای تعامل با کامپوننت های نیتیو استفاده میکنه در زمان اجرا و عملا کد نیتیوی تولید نمیکنه، فلاتر واقعا خروجی نیتیو تولید میکنه. اما فلاتر دو مشکل اساسی داشت، همونطور که گفتم سختی انتخاب تکنولوژی برقراری تعادل بین منابعی که دارید و میزان ایده عال بودن یک تکنولوژی نسبت به پروژه شماست.مشکل اول اینکه ، تیم ما قبلا React Native کار کرده بود و دانش جاوااسکریپتی داشت. برای ورود به Flutter باید Dart یاد می گرفت.خب این یعنی زمان بیشتر و سرعت کمتر. این تکنولوژی در سال 2018 مطرح شده و مشکل دوم ریسک جدید بودن فلاتر بود.هر چقدر هم که توسعه دهندگان قول پشتیبانی قوی رو بدن ، نمی تونستیم خیالمون رو از رویارویی با مسائل پیش بینی نشده در یک پروژه جدی راحت کنیم. باید این سوال رو از خودمون می پرسیدم React Native چقدر بدتر از Flutter هست؟ آیا به اندازه ای هست که هزینه یادگیری و ریسک استفاده از اون رو بپردازیم؟ در نهایت ما به این نتیجه رسیدیم که با توجه به کتابخونه های آماده React Native از پروژه های قبلی، مهارت و تسلط تیم بر روی این تکنولوژی و کارایی نسبتا خوبش علارغم مشکلاتی که داره و در مجموع منابعی که در اختیار داریم از این تکونولوژی استفاده کنیم و استفاده از Flutter رو به زمان مناسب تری موکول کنیم. هر چند خروجی Pwa یکی از موارد مهم برای ما بود که React بصورت رسمی ازش پشتیبانی نمیکنه اما خب راه حل های ثانویه براش وجود داره.در نهایت مثل همیشه من هیچ نسخه جامعی ندارم که برای همه تیم ها تجویز کنم، با توجه به انتظارات و منابعی که در اختیار دارید و نقاط ضعف و قوت هر تکنولوژی یک حالت متعادل وجود داره که باید ازش استفاده کرد. البته که من همیشه از ریسک ورود به تکنولوژی های جدید استقبال می کنم به شرطی که بتونم هزینه این ریسک رو بپردازم.</description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>mehdi geran</author>
                <pubDate>Fri, 01 May 2020 22:08:42 +0430</pubDate>
            </item>
                    <item>
                <title>آموزش react navigation5</title>
                <link>https://virgool.io/iran-react-community/react-navigation-latest-version5-gpfiroiiunrd</link>
                <description>با تازگی نسخه 5 کتابخانه react navigation با کلی تغییر منتشر شد.اگر نمیدونید که react navigation چی هست باید خدمتتون عرض کنم که وظیفه این کتابخانه مدیریت صفحات مختلف شما در react native است .react navigation در نسخه جدید دچار تغییرات خیلی زیادی حتی در نحوه نصب شده که در این مقاله این موارد رو به صورت کامل بررسی می کنیم.همچنین می تونید دوره آموزشی کار با react navigation 5  رو به صورت رایگان در سایت مشاهده کنید.1. اولین گام باید آخرین نسخه این کتابخانه را نصب کنیم.برای اینکار دایرکتوری پروژه را در cmd باز می کنیم و دستور زیر را اجرا میکنیم.npm install @react-navigation/nativeاسکرین شات بعد از نصب2. حالا باید کتابخانه های reanimated, gesture handler, react native screens, react native safe area و masked viewرو نصب کنیم.پس  دایرکتوری پروژه رو در  Command Prompt باز میکنیم و دستور زیر را اجرا میکنیم.این کتابخانه ها برای استفاده React Navigation اجباری هستند.npm install react-native-reanimated react-native-gesture-handler react-native-screens react-native-safe-area-context @react-native-community/masked-viewاسکرین شات بعد از نصب3. در گام بعدی باید کتابخانه  Stack Navigator رو  نصب کنیم.دستور زیر را مجدد در دایرکتوری پروژه برای نصب این کتابخانه اجرا می کنیم.npm install @react-navigation/stackاسکرین شات بعد از نصب4. حالا پروژه آماده استفاده از React Navigation 5.x است.بخش بعدی استفاده از این کتابخانه و شروع کدزدن است.بنابراین فایل App.js  رو باز کنید و react-native-gesture-handler  رو ایمپورت کنید.اگر react-native-gesture-handler رو ایمپورت نکنیم در حالت debug به ما خطایی نشان نمیده ولی صد در صد در APK با error روبرو خواهید شد.import &#039;react-native-gesture-handler&#039;;5.ایمپورت StyleSheet, Text, View  و Button در App.js:import * as React from &#039;react&#039;;
import { StyleSheet, Text, View, Button } from &#039;react-native&#039;;6. ایمپورت NavigationContainer  و createStackNavigator  از کتابخانه  react navigation :import { NavigationContainer } from &#039;@react-navigation/native&#039;;
import { createStackNavigator } from &#039;@react-navigation/stack&#039;;7. ایجاد یک تابع به نام HomeScreen  با  navigation prop.این تابع در واقع Home Screen ما خواهد بود.در آخرین نسخه React Navigation ساختار کدنویسی برنامه بهبود یافته است و ما راحت تر می توانیم View ها رو ایجاد کنیم:function HomeScreen({ navigation }) {
navigateToScreen=()=&gt;{
navigation.navigate(&#039;Second&#039;);
}
return (
&lt;View style={styles.MainContainer}&gt;
&lt;Text style={styles.text}&gt; Home Screen &lt;/Text&gt;
&lt;Button onPress={this.navigateToScreen} title=&amp;quotNavigate To Second Screen&amp;quot /&gt;
&lt;/View&gt;
);
}8.ایجاد یک تابع دیگر به نام SecondScreen.این دومین screen ما خواهد بود.function SecondScreen() {
return (
&lt;View style={styles.MainContainer}&gt;
&lt;Text style={styles.text}&gt; Second Screen &lt;/Text&gt;
&lt;/View&gt;
);
}9. استفاده از ()createStackNavigatorconst Stack = createStackNavigator();10.ایجاد یک تابع به نام App و قرار دادن Stack.Screen  با نام screen ها و wrap کردن درون  Stack.Navigator و Navigation Container .function App() {
return (
&lt;NavigationContainer&gt;
&lt;Stack.Navigator&gt;
&lt;Stack.Screen name=&amp;quotHome&amp;quot component={HomeScreen} /&gt;
&lt;Stack.Screen name=&amp;quotSecond&amp;quot component={SecondScreen} /&gt;
&lt;/Stack.Navigator&gt;
&lt;/NavigationContainer&gt;
);
}11.ایجاد استایلconst styles = StyleSheet.create({
MainContainer: {
flex: 1,
justifyContent: &#039;center&#039;,
alignItems: &#039;center&#039;
},
text: {
textAlign: &#039;center&#039;,
margin: 12,
fontSize: 22,
fontWeight: &amp;quot100&amp;quot,
},
});12. کلمه کلیدی  export default  را برای کامپوننت App در انتهای این فایل قرار دهید تا به صورت خودکار تمامی view ها render شوند.export default App;13. کد کامل برنامه در فایل App.jsimport &#039;react-native-gesture-handler&#039;;
import * as React from &#039;react&#039;;
import { StyleSheet, Text, View, Button } from &#039;react-native&#039;;
import { NavigationContainer } from &#039;@react-navigation/native&#039;;
import { createStackNavigator } from &#039;@react-navigation/stack&#039;;
function HomeScreen({ navigation }) {
navigateToScreen=()=&gt;{
navigation.navigate(&#039;Second&#039;);
}
return (
&lt;View style={styles.MainContainer}&gt;
&lt;Text style={styles.text}&gt; Home Screen &lt;/Text&gt;
&lt;Button onPress={this.navigateToScreen} title=&amp;quotNavigate To Second Screen&amp;quot /&gt;
&lt;/View&gt;
);
}
function SecondScreen() {
return (
&lt;View style={styles.MainContainer}&gt;
&lt;Text style={styles.text}&gt; Second Screen &lt;/Text&gt;
&lt;/View&gt;
);
}
const Stack = createStackNavigator();
function App() {
return (
&lt;NavigationContainer&gt;
&lt;Stack.Navigator&gt;
&lt;Stack.Screen name=&amp;quotHome&amp;quot component={HomeScreen} /&gt;
&lt;Stack.Screen name=&amp;quotSecond&amp;quot component={SecondScreen} /&gt;
&lt;/Stack.Navigator&gt;
&lt;/NavigationContainer&gt;
);
}
const styles = StyleSheet.create({
MainContainer: {
flex: 1,
justifyContent: &#039;center&#039;,
alignItems: &#039;center&#039;
},
text: {
textAlign: &#039;center&#039;,
margin: 12,
fontSize: 22,
fontWeight: &amp;quot100&amp;quot,
},
});
export default App;اگر این مقاله براتون مفید بود،اون رو با دوستان و همکاراتون به اشتراک بزارید. اگر قصد دارید مقالات تخصصی بیشتری در زمینه React Native مطالعه کنید پیشنهاد میکنم به بخش آموزش متنی سایت مراجعه کنید.همچنین اگر قصد دارید به عنوان یک برنامه نویسی حرفه ای React Native فعالیت کنید پیشنهاد میکنم دوره آموزش ساخت اپلیکیشن فروشگاهی مشابه digikala با react native رو مشاهده کنید.[منبع]</description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>reactapp.ir</author>
                <pubDate>Sun, 19 Apr 2020 20:49:56 +0430</pubDate>
            </item>
                    <item>
                <title>آموزش کار با انیمیشن(Easing Animation) در React Native</title>
                <link>https://virgool.io/iran-react-community/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%DA%A9%D8%A7%D8%B1-%D8%A8%D8%A7-%D8%A7%D9%86%DB%8C%D9%85%DB%8C%D8%B4%D9%86easing-animation-%D8%AF%D8%B1-react-native-dv2qwmycfjyk</link>
                <description> در واقع Easing یک انیمیشن برای توضیح انواع متفاوت animations است.منظور از animation easing این است که انواع مختلفی از حرکت رو روی یک object مثل شروع سریع و توقف آهسته رو پیاده کند.این روند کند شدن decelerates the object نامیده می شود.4 نوع از easing در react native animation وجود دارد.در این نوع مقاله ما هر 4 نوع easing و نحوه پیاده سازی اون در React Native را یاد میگیریم.حالا بهتره که بریم سراغ کدنویسی:ایمپورت Animated, StyleSheet, View, TouchableWithoutFeedback در فایل App.jsimport React, {Component} from &#039;react&#039;;
import { Animated, StyleSheet, View, TouchableWithoutFeedback, Easing } from &#039;react-native&#039;;ایجاد یک class به نام App.این class کامپوننت اصلی ما در برنامه خواهد بودexport default class App extends Component {
}ایجاد ()constructor برای App.درون ()constructor  یک state به نام animationValue با مقدار پیش فرض صفر ایجاد می کنیم.ما از این state برای تغییر سرعت،شروع و پایان انیمیشن استفاده می کنیم.constructor(){
super();
this.state={
animationValue : new Animated.Value(0)
}
} https://virgool.io/p/dv2qwmycfjyk/edit از toValue  برای مشخص کردن فاصله انیمیشن استفاده می شوداز duration برای مشخص کردن مدت زمانی که شروع تا پایان انیمیشن استفاده می شود.4 نوع مختلفی از انیمیشن Easing که داریم به صورت زیر است:Easing.bounceEasing.backEasing.elasticEasing.bezierstartAnimation=()=&gt;{
Animated.timing(this.state.animationValue,{
toValue : 270,
duration : 500,
// easing: Easing.bounce,
// easing : Easing.back(10),
// easing : Easing.elastic(5),
easing : Easing.bezier(.07, 1, .33, .89),
}).start();
}ایجاد یک متغیر به نام animatedStyle  در بلاک render’s.حالا ما مقدار translateY  رو با استفاده از animationValue بروزرسانی می کنیم.render() {
const animatedStyle = {
transform: [{ translateY : this.state.animationValue }],
}
return (
);
}ایجاد یک View اصلی به render’s return.حالا یک کامپوننت Animated.View که درون TouchableWithoutFeedback  قرار می دهیم.و در onPress مربوط به این Button انیمیشن انجام خواهد شد.انیمیشن بر روی Animated.View انجام خواهد شد.render() {
const animatedStyle = {
transform: [{ translateY : this.state.animationValue }],
}
return (
&lt;View style={styles.MainContainer}&gt;
&lt;TouchableWithoutFeedback onPress={this.startAnimation}&gt;
&lt;Animated.View style={[styles.animatedBox, animatedStyle]} &gt;
&lt;/Animated.View&gt;
&lt;/TouchableWithoutFeedback&gt;
&lt;/View&gt;
);
}ایجاد styleconst styles = StyleSheet.create({
MainContainer: {
flex: 1,
justifyContent: &#039;center&#039;,
alignItems : &#039;center&#039;,
padding: 12
},
animatedBox:
{
width : 100,
height: 100,
backgroundColor : &#039;#0091EA&#039;
}
});کد کامل برنامه در فایل App.jsimport React, {Component} from &#039;react&#039;;
import { Animated, StyleSheet, View, TouchableWithoutFeedback, Easing } from &#039;react-native&#039;;
export default class App extends Component {
constructor(){
super();
this.state={
animationValue : new Animated.Value(0)
}
}
startAnimation=()=&gt;{
Animated.timing(this.state.animationValue,{
toValue : 270,
duration : 500,
// easing: Easing.bounce,
// easing : Easing.back(10),
// easing : Easing.elastic(5),
easing : Easing.bezier(.07, 1, .33, .89),
// easing : Easing.ease(20)
}).start();
}
render() {
const animatedStyle = {
transform: [{ translateY : this.state.animationValue }],
}
return (
&lt;View style={styles.MainContainer}&gt;
&lt;TouchableWithoutFeedback onPress={this.startAnimation}&gt;
&lt;Animated.View style={[styles.animatedBox, animatedStyle]} &gt;
&lt;/Animated.View&gt;
&lt;/TouchableWithoutFeedback&gt;
&lt;/View&gt;
);
}
};
const styles = StyleSheet.create({
MainContainer: {
flex: 1,
justifyContent: &#039;center&#039;,
alignItems : &#039;center&#039;,
padding: 12
},
animatedBox:
{
width : 100,
height: 100,
backgroundColor : &#039;#0091EA&#039;
}
});اگر این مقاله براتون مفید بود،اون رو با دوستان و همکاراتون به اشتراک بزارید.همچنین اگر قصد دارید به عنوان یک برنامه نویسی حرفه ای React Native فعالیت کنید پیشنهاد میکنم دوره آموزش ساخت اپلیکیشن فروشگاهی مشابه digikala با react native رو مشاهده کنید.منبعاسکرین شات</description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>reactapp.ir</author>
                <pubDate>Wed, 08 Apr 2020 21:17:44 +0430</pubDate>
            </item>
                    <item>
                <title>استفاده از env در react-native</title>
                <link>https://virgool.io/iran-react-community/%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-env-%D8%AF%D8%B1-react-native-ucaeddqo58rs</link>
                <description>در زمان توسعه اپ‌ها بزرگ شاید یکی از مهمتری نیازهای روز استفاده از env باشه. البته شما میتونید از env در اپ‌های کوچیک هم استفاده کنید که این بسته به تشخص شما و نیاز شماست. در زمان استفاده از react-native کانفیگ کردن env به شدت سخته به نظر من و دردسر های زیادی رو میتونه ایجاد بکنه براتون و به همین دلیل پیشنهاد نمیشه کسی اینکار رو خودش انجام بده.بعضی افراد هم هستن میخوان این مورد رو دور بزنن و زرنگ بازی در بیارن برای همین یک فایل به طور مثال index.js میسازن و متغیر‌ها رو اونجا قرار میدن به عنوان constant که زیاد جالب نیست چرا که اگر شما چند محیط مختلف داشته باشید مثل محیط‌های زیرdevelopmenttestproductionنمیتونید از این متغیر ها استفاده بکنید و مشکلاتی رو ایجاد میکنه.اینجا میخوام بهتون یک پکیج رو معرفی کنم به راحتی به کمک اون میتونید در react-native از env استفاده بکنید. که نصب و استفاده از اون بسیار سادست. البته جامعه بسیار قویی هم داره و در خیلی از جاها از اون استفاده شدهکه میتونید به این لینک برید و توضیحات تکمیلی رو ببینید. برای نصب این پکیج به سادگی باید دستور زیر رو در ترمینال وارد کنید.npm install react-native-config
// or
yarn add react-native-configیکم باید صبر کنید تا پکیج نصب بشه بعد از اون میتونید یک فایل env در مسیر اصلی پروژتون ایجاد کنید و متغیرها رو تعریف کنید.برای android باید یک کار دیگه هم انجام بدید.به مسیر روبرو برید android/app/build.gradle و خط زیر رو بهش اضافه کنید.// 2nd line, add a new apply:
apply from: project(&#039;:react-native-config&#039;).projectDir.getPath() + &amp;quot/dotenv.gradle&amp;quotنکته: اگر در زمان توسعه متغیر ها رو تغییر دادید برای اینکه تغییرات اعمال بشه و مقادیر صحیح جدید رو داشته باشید باید یکبار مجدد از برنامه build بگیرید و بعد برنامه رو start کنید.روش استفاده به این صورت هستش که در هر فایل js که خواستید از این متغیر‌ها استفاده بکنید باید به روش زیر باشهimport Config from &#039;react-native-config&#039;;از حالا با کمک متغیر Config به تمام متغیرهایی که در env تعریف کردید دسترسی دارید.</description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>farshadfahimi</author>
                <pubDate>Mon, 06 Apr 2020 00:21:26 +0430</pubDate>
            </item>
                    <item>
                <title>ایجاد Search Bar Filter در React Native به صورت Real Time</title>
                <link>https://virgool.io/iran-react-community/search-bar-filter-on-flatlist-json-data-in-react-native-in0mnmxuhds3</link>
                <description> استفاده از Search Bar filter برای فیلتر کردن خودکار داده ها در اپلیکیشن های موبایل،یک روش رایج است.همونطور که همگی ما میدونیم استفاده از search bar filter تقریبا در هر اپلیکیشن android یا ios وجود دارد.در این مقاله قصد داریم در React Native یک  Search Bar filter با استفاده از flatList ایجاد کنیم.برای دریافت اطلاعات ما از JSONPlaceholder استفاده میکنم که اطلاعات رو به صورت json و رایگان در اختیار ما قرار میده.بریم سراغ کد نویسیفایل App.js رو باز کنید و کامپوننت های ActivityIndicator, Alert, FlatList, Text, StyleSheet, View و TextInput رو ایمپورت کنیدimport React, { Component } from &#039;react&#039;;
import { ActivityIndicator, Alert, FlatList, Text, StyleSheet, View, TextInput } from &#039;react-native&#039;;2. درون این فایل یک کلاس به نام App ایجاد میکنم که کلاس اصلی ما در این مثال است.export default class App extends Component {
}3. برای کلاس App سازنده یا همون ()constructor رو تعریف می کنیم و 3 state به نام های isLoading و text و data تعریف میکنیم.همچینینarrayholder رو در ()constructor ایجاد می کنیم.constructor(props) {
super(props);
this.state = {
isLoading: true,
text: &#039;&#039;,
data: []
}
this.arrayholder = [];
}از isLoading برای نمایش spinner تا زمانی که اطلاعات از سرور به دست ما می رسد استفاده میشه.از text برای ذخیره کاراکتری هایی که کاربر وارد میکنه، استفاده میشهاز data برای ذخیره داده هایی که از سرور برای ما برگشت داده میشه، استفاده میشهاز arrayholder برای فیلتر کردن داده ها استفاده میشه.4. در این گام componentDidMount() رو تعریف می کنیم و درون این lifecycle درخواست به سرور میزنیم و اطلاعات دریافتی رو در data و arrayholder  ذخیره می کنیم.5. ایجاد یک تابع به نام ()GetFlatListItem با name argument.از این تابع برای نمایش نام آیتم کلیک شده استفاده می کنیم.GetFlatListItem(name) {
Alert.alert&#40;name&#41;;
}6. ایجاد یک تابع دیگه به نامsearchData() با text argument.این تابع در ()Text فیلدی که در نظر گرفتیم فراخوانی میشه.بنابراین هر زمانی که کاربر شروع به تایپ کردن در این textInput کنه اطلاعات ما بر اساس کاراکترهای واردشده فیلتر میشه.7. ایجاد یک تابع به نام ()itemSeparator.با استفاده از این تابع ما یک خط افقی بین هر کدوم از آیتم ها قرار میدیم.این تابع در رویداد ()ItemSeparatorComponent مربوط به flatList فراخوانی می شود.itemSeparator = () =&gt; {
return (
&lt;View
style={{
height: .5,
width: &amp;quot100%&amp;quot,
backgroundColor: &amp;quot#000&amp;quot,
}}
/&gt;
);
}8. اضافه کردن TextInput و FlatList در بلاک render’s return کامپوننتrender() {
if (this.state.isLoading) {
return (
&lt;View style={{flex: 1, paddingTop: 20}}&gt;
&lt;ActivityIndicator /&gt;
&lt;/View&gt;
);
}
return (
&lt;View style={styles.MainContainer}&gt;
&lt;TextInput
style={styles.textInput}
Text={(text) =&gt; this.searchData(text)}
value={this.state.text}
underlineColorAndroid=&#039;transparent&#039;
placeholder=&amp;quotSearch Here&amp;quot /&gt;
&lt;FlatList
data={this.state.data}
keyExtractor={ (item, index) =&gt; index.toString() }
ItemSeparatorComponent={this.itemSeparator}
renderItem={({ item }) =&gt; &lt;Text style={styles.row}
onPress={this.GetFlatListItem.bind(this, item.name)} &gt;{item.name}&lt;/Text&gt;}
style={{ marginTop: 10 }} /&gt;
&lt;/View&gt;
);
}9. ایجاد استایلconst styles = StyleSheet.create({
MainContainer: {
justifyContent: &#039;center&#039;,
flex: 1,
margin: 5,
},
row: {
fontSize: 18,
padding: 12
},
textInput: {
textAlign: &#039;center&#039;,
height: 42,
borderWidth: 1,
borderColor: &#039;#009688&#039;,
borderRadius: 8,
backgroundColor: &amp;quot#FFFF&amp;quot
}
});10.کد کامل فایل App.jsimport React, { Component } from &#039;react&#039;;
import { ActivityIndicator, Alert, FlatList, Text, StyleSheet, View, TextInput } from &#039;react-native&#039;;
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: true,
text: &#039;&#039;,
data: []
}
this.arrayholder = [];
}
componentDidMount() {
return fetch(&#039;https://jsonplaceholder.typicode.com/users&#039;)
.then((response) =&gt; response.json())
.then((responseJson) =&gt; {
// console.log(responseJson);
this.setState({
isLoading: false,
data: responseJson,
}, () =&gt; {
// In this block you can do something with new state.
this.arrayholder = responseJson;
});
})
.catch((error) =&gt; {
console.error(error);
});
}
GetFlatListItem(name) {
Alert.alert&#40;name&#41;;
}
searchData(text) {
const newData = this.arrayholder.filter(item =&gt; {
const itemData = item.name.toUpperCase();
const textData = text.toUpperCase();
return itemData.indexOf(textData) &gt; -1
});
this.setState({
data: newData,
text: text
})
}
itemSeparator = () =&gt; {
return (
&lt;View
style={{
height: .5,
width: &amp;quot100%&amp;quot,
backgroundColor: &amp;quot#000&amp;quot,
}}
/&gt;
);
}
render() {
if (this.state.isLoading) {
return (
&lt;View style={{flex: 1, paddingTop: 20}}&gt;
&lt;ActivityIndicator /&gt;
&lt;/View&gt;
);
}
return (
&lt;View style={styles.MainContainer}&gt;
&lt;TextInput
style={styles.textInput}
Text={(text) =&gt; this.searchData(text)}
value={this.state.text}
underlineColorAndroid=&#039;transparent&#039;
placeholder=&amp;quotSearch Here&amp;quot /&gt;
&lt;FlatList
data={this.state.data}
keyExtractor={ (item, index) =&gt; index.toString() }
ItemSeparatorComponent={this.itemSeparator}
renderItem={({ item }) =&gt; &lt;Text style={styles.row}
onPress={this.GetFlatListItem.bind(this, item.name)} &gt;{item.name}&lt;/Text&gt;}
style={{ marginTop: 10 }} /&gt;
&lt;/View&gt;
);
}
}
const styles = StyleSheet.create({
MainContainer: {
justifyContent: &#039;center&#039;,
flex: 1,
margin: 5,
},
row: {
fontSize: 18,
padding: 12
},
textInput: {
textAlign: &#039;center&#039;,
height: 42,
borderWidth: 1,
borderColor: &#039;#009688&#039;,
borderRadius: 8,
backgroundColor: &amp;quot#FFFF&amp;quot
}
});اگر این مقاله براتون مفید بود،اون رو با دوستان و همکاراتون به اشتراک بزارید.همچنین اگر قصد دارید به عنوان یک برنامه نویسی حرفه ای React Native فعالیت کنید پیشنهاد میکنم دوره آموزش ساخت اپلیکیشن فروشگاهی مشابه digikala با react native رو مشاهده کنید.اسکرین شات :منبع</description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>reactapp.ir</author>
                <pubDate>Wed, 01 Apr 2020 17:10:48 +0430</pubDate>
            </item>
                    <item>
                <title>از تشخیص کلیک خارج از کامپوننت تا Type Assertions در تایپ‌اسکریپت</title>
                <link>https://virgool.io/iran-react-community/%D8%A7%D8%B2-%D8%AA%D8%B4%D8%AE%DB%8C%D8%B5-%DA%A9%D9%84%DB%8C%DA%A9-%D8%AE%D8%A7%D8%B1%D8%AC-%D8%A7%D8%B2-%DA%A9%D8%A7%D9%85%D9%BE%D9%88%D9%86%D9%86%D8%AA-%D8%AA%D8%A7-type-assertions-%D8%AF%D8%B1-%D8%AA%D8%A7%DB%8C%D9%BE%D8%A7%D8%B3%DA%A9%D8%B1%DB%8C%D9%BE%D8%AA-c3c0n1znrykd</link>
                <description>گاهی اوقات پیش میاد که باید بیشتر به Typescript بفهمونید که تایپ متغییرتون چیه و همین‌جوری نمیفهمه و با ارور کامپایلر مواجه می‌شید. اینجاست که Type Assertions به کمک شما میاد و مشکلتون را حل میکنه. Type Assertions از ورژن 1.6 به بعد تایپ‌اسکریپت در دسترسه و می‌‌تونید ازش استفاده کنید.قرار بود با react.js یه کامپوننت طراحی کنم که یک حالت مهم در اون کامپوننت زمانی اتفاق می‌افتاد که خارج از کامپوننت کلیک می‌شد. کلا تشخیص اینکه خارج از کامپوننت کلیک شده یه موضوع پر بحث در react.js هست. برای حل این چالش روش های مختلفی وجود داره حتی یه پکیج پرطرفدار برای آن ساخته شده است. من با یکمی تحقیق فهمیدم که بهترین و سریع‌ترین روش ممکن استفاده از تکنیک فوکوس/بلور است. چون هیچگونه EventListenerای به کامپومننت اضافه نمی‌کنه بالاترین پرفورمنس را به ما می‌ده.مشکل اینجا به وجود اومد که من داخل کامپوننتم از یه تگی استفاده کرده بودم که position آن absolute و اندازه‌ی آن بزرگتر اندازه‌ی تگ پدرش (parent) بود و بخاطر ساز و کار مرورگر (یا باگ) زمانی که روی آن تگ absolute کلیک می‌شد بجای اینکه تگ پدرش focus شود تگ پدرش blur می‌شد. با یکمی سرچ فهمیدم که باید یه فیلتر سر راه  تگ پدر (parent) بزارم تا مشکلش حل شود.اینجا دیگه مشکلم حل شده بود و به راحتی می‌تونستم کلیک کردن خارج از کامپوننت را تشخیص بدم. ولی تایپ‌اسکریپت یه ارور می‌داد که خیلی رو مخ بود:مشکل اینه که تابع event.currentTarget.contains() یه آرگمان می‌پذیره که باید از نوع Node باشه ولی event.relatedTarget که به عنوان ورودی به تابع داده‌ایم تایپش EventTarget است. چون EventTarget  یک تایپ عمومی است و Node یکی از زیر مجموعه های آن است.Basically EventTarget is the most general type, of which Element is a subtype, and HTMLElement is a subtype of that. If you get back a thing from the DOM, we generally have no idea which it is, and you should add a type assertion to &quot;add in&quot; the specific external knowledge that you have about the structure of your particular DOM layout.It&#x27;s possible, for example, that the .target of an event is not an Element (you can add event listeners to XMLHttpRequest, for example, and XMLHttpRequest does not have a getBoundingClientRect method).ولی اینجا مطمئن هستیم که EventTarget  از نوع Element یا همون Node هست. بنابراین باید به صورت صریح به typescript بفهمونیم اینجا EventTarget از نوع Node است.Type assertionsبا استفاده از Type assertions می‌تونیم به تایپ‌اسکریپت به صورت صریح اعلام کنیم که من مطئمنم تایپ متغییر اینه و بهمون ارور نده لطفا. مثل Type Casting در بقیه‌ی زبانهای برنامه‌نویسی با این تفاوت که در run-time هیچ اتفاقی نمی‌افته. سینتکس Type assertions به صورت زیر است:&lt;Type&gt; UnaryExpressionچون سینتکس بالا با JSX (و TSX) تداخل داره می‌تونیم از سینتکس جایگزین زیر استفاده کنیم:UnaryExpression as Typeاگه ما از Type assertions استفاده کنیم و به صورت صریح اعلام کنیم که تایپ event.relatedTarget از نوع Node است کامپوننت نهایی ما به صورت زیر می‌شود و هیچگونه اروری دریافت نمی‌کنیم ?</description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>مسیح جهانگیری</author>
                <pubDate>Thu, 06 Feb 2020 18:11:21 +0330</pubDate>
            </item>
                    <item>
                <title>رفقای خوب (Gatsby+Netlify)</title>
                <link>https://virgool.io/iran-react-community/%D8%B1%D9%81%D9%82%D8%A7%DB%8C-%D8%AE%D9%88%D8%A8-gatsbynetlify-mwarqiiut4yt</link>
                <description>goodfellasاحتمالا عنوان این پست شما رو به یاد یکی از شاهکار های مارتین اسکورسیزی بندازه ! اگه حتی این فیلم رو ندیدید و یا رابرت دنیرو رو یادتون نمیاد نگران نباشید :) قراره این بار یک رفقای خوب دیگه رو بخونید به کارگردانی جاوا اسکریپت و تولد یک ستاره ی جدید به نام گتسبی !اول از همه باید بهتون بگم که این پست خیلی طولانی میشه چون قراره یک پروژه رو با گتسبی و نتلیفای بالا بیاریم و کامل توضیح بدیم پس اگه الان فرصتش رو ندارید حتما این مقاله رو بوکمارک کنید تا بعد ها به سراغش بیاید.مقدمهچند وقتی هست که مبحثی به نام JAM Stack روز به روز ترند تر میشه. قطعا تا الان با استک های مختلفی مثل MERN،MEAN و یا حتی LAMP آشنایی دارید.اما JAM Stack مخفف شده ی عبارت Javascript API Markup هست که برخلاف باقی استک ها قصد معرفی ابزار نداره و یک جور طرز تفکرهقسمت  که خب کاملا مشخصه قراره بر محور جاوا اسکریپت و فریمورک ها و کتابخونه هاش بچرخیم.قسمت API : یه سری reusable API ها هست که عمدتا می تونید از api as service ها استفاده کنید.قسمت Markup : اگه با مجموعه زبان Markup آشنایی ندارید توصیه میکنم این مقاله رو بخونید. اما به صورت خلاصه می تونم بگم که یک مجموعه زبان نشانه گذاری هست برای توصیف متن ها در علم کامپیوتر که بهش شبه زبان برنامه نویسی ام میگن.حالا JAM Stack مگه چیه که داره ترند میشه؟خب این معماری وب یک سری مزایایی داره که دیگر معماری ها ندارن مثل :پرفومنس بیشترخیلی خیلی ایمن ترارزانترسرعت توسعه و تجربه ی توسعه ی بهترمقیاس پذیریبرای توضیح بیشتر هر کدوم از این دلایل می تونید به این سایت مراجعه کنید و یا منتظر بمونید تا انتهای مقاله که موارد بالا رو درک کنیم باهم :)تیتراژ ابتدایی با گتسبیخب ما واسه ی پیاده سازی یک JAM Stack ساده از گتسبی و نتلیفای استفاده می کنیم.گتسبی چیه : گتسبی یک فریمورک بر پایه ی ری اکت هست که باهاش می تونید SSG درست کنید.نتلیفای چیه: یک شرکت کلاود کامپیوتینگ هست که به automate کردن وب اپلیکیشن های مدرن می پردازه.ما قصد داریم با استفاده از Gatsby به عنوان بخش Javasciprt و Netlify CMS به عنوان بخش reusable API به تولید Markup بپردازیم و یک وبلاگ ساده رو با این معماری وب بسازیم.قبل از هرچیزی چند خط بالاتر از کلمه ی SSG استفاده کردم که برای اینکه هم بیشتر با گتسبی آشنا بشید و هم برخی از مزیت های استفاده از اون رو درک کنید توصیه میکنم ابتدا دموی پروژه مون رو ببینید و مقاله ی مندرج شده در اون رو بخونید و دوباره به همین جا برگردید.دموی پروژه( برای خوندن مقاله روی عنوان مقاله کلیک کنید )شروع پروژه با ایجاد ساختارخب برگشتید؟ چطور بود دمو؟ بنظر من که این SSG ها ( در vue.js مانند Gridsome ) خیلی حس بهتری به کاربر ارائه میدن :دی !اول از همه باید بگم پیش نیاز این پروژه آشنایی شما با ری اکت هست و بسو اما چیز هایی که برای شروع این پروژه نیاز دارید :یک پروژه ی گتسبی ( که باهم ایجادش می کنیم )یک اکانت گیت هابیک اکانت Netlifyایجاد یک پروژه گتسبیابتدا لازم هست که gatsby-cli رو نصب کنید مانند دستور زیر :npm install -g gatsby-cliببینید گتسبی یه سری استارتر داره یعنی یه سری پروژه های از قبل کانفیگ شده ی آماده برای شروع کارشما با دستور زیر می تونید یک پروژه گتسبی بسازید که از استارتر دیفالت استفاده می کنه اما من توصیه میکنم این کار رو نکنید و برای این پروژه از استارتر hello world استفاده کنید تا تموم فایل ها و کانفیگ های پروژه رو خودمون انجام بدیم ( بنده به بیماری خود کانفیگی دچار هستم )// uses default starter
gatsby new [project-name]
// Follow these instructions
gatsby new hello-world https://github.com/gatsbyjs/gatsby-starter-hello-world
cd hello-world
gatsby developخب تا الان شما یک پروژه گتسبی رو بالا آوردید و ظاهرش رو مشاهده می کنید.بریم به قسمت دوم و پروژه رو بیاریم روی گیت :git remote add origin https://github.com/[YOUR-GITHUB-USERNAME]/[YOUR-REPO-NAME].git
git push -u origin masterحالا بریم سراغ ساخت یک اکانت توی نتلیفایبه سایت نتلیفای برید.یک اکانت بسازید و لاگین کنید.روی New site from Git کلیک کنید.روی گیت هاب که زیر Continuous Deployment قرار داره کلیک کنید. ( خب الان نیازه که به نتلیفای اجازه بدید تا به گیت هابتون دسترسی داشته باشه )حالا ریپوی مربوط به پروژتون رو انتخاب کنید.و در آخر روی Deploy site کلیک کنید.خب الان برای شما یک سابدومین ساخته شده در نتلیفای و همچنین لینک شده به برنچ مستر ریپوی پروژتون به این منظور که هر تغییراتی که توی برنچ مستر ریپوی شما انجام بشه به صورت اتوماتیک نتلیفای یک بیلد میگیره و شما نتایج رو توی این سابدومین مشاهده خواهید کرد.اما این رو باید هم به گیتهاب هم به نتلیفای بفهمونیمچطوری به گیتهاب بفهمونیم : وارد گیتاب بشید در قسمت setting و developer setting روی OAuth app کلیک کنید و یکی جدید بسازید. اسمش هرچیزی می تونه باشه و برای home page url همون آدرس سابدومینی که نتلیفای براتون ساخته رو بزارید و در قسمت authorisation callback URL مقدار زیر رو بزارید و روی Register Application بزنید.https://api.netlify.com/auth/doneخب حالا بهتون یک client ID و یک client secret میده که داشته باشیدش نیازش داریم :دیچطوری به نتلیفای بفهمونیم: وارد نتلیفای بشید و به قسمت تنظیمات سایتتون برید در منوی Access control بر روی OAuth کلیک کنید. روی Install Provider کلیک کنید و پس از انتخاب گیتهاب client ID و client secret رو وارد کنید.نصب کردن Netlify CMSخب دوستان قبل از نصب سیستم مدیریت محتوای نتلیفای ( یا خدا فارسیش چقدر طولانیه :)) ) باید بهتون بگم که گتسبی یک سری پلاگین داره که برای ارتباط با API هاش ازشون استفاده می کنه و تقریبا برای هرچیزی که فکرشو بکنید یک پلاگین داره اما اگر نداشت هم نگران نباشید چون به راحتی میتونید براش بنویسید :)برای نصب Netlify CMS و پلاگینش از دستور زیر استفاده می کنیم:npm install --save netlify-cms gatsby-plugin-netlify-cmsپس از نصب هر پلاگین در گتسبی شما باید به گتسبی بفهمونید که این پلاگین نصب شده پس در فایل gatsby-config.js باید کانفیگ پلاگین رو وارد کنید ( نگران نباشید چون همه ی این کانفیگ ها به همراه پلاگین در اینجا قرار دارند )پس تنظیمات زیر رو در فایل gatsby-config.js خودتون وارد کنید :// In your gatsby-config.js file
module.exports = {
plugins: [
// ... other plugins
 `gatsby-plugin-netlify-cms`
// ... other plugins
],
}خب دست به گیرنده هاتون نزنید تا اینجا ما ساختار پروژمون رو ساختیم و اما یه توضیح کوچیک در مورد فایل هایی که توی گتسبی می بینید بدم و بریم سراغ ادامه ی پروژه :src : هسته ی تمام کدهایی که شما می نویسید توی این پوشه است که از چند زیر پوشه تشکیل شدهsrc/components : دقیقا مثل ری اکت اینجا هم قراره کامپوننت بنویسیمsrc/pages : هر فایلی که در این پوشه قرار بگیره یک صفحه جداگانه میسازه و دیگه لازم نیست شما از پکیج های روتر استفاده کنید.git-config.js : منبع اصلی کانفیگ پلاگین های شما و همچنین به صورت کلی هر کانفیگی که در مورد اپ دارید.و باقی فایل ها که فایل های مرسوم پروژه ها هست و فایل هایی که بعد ها به پروژمون اضافه خواهد شد.تا اینجا ساختار فایل های پروژه ی شما باید مثل زیر باشه :-node_modules
- src
   -components
   -pages
.gitignore
.prettierignore
.prettierrc
gatsby-config.js
LICENSE
package-lock.json
package.json
README.mdخب تازه میخوایم پروژه رو شروع کنیم و امیدوارم که خسته نشده باشید :دیواکنش اون دسته از دوستانی که خسته شدنپیکربندی Netlify CMSبعد از یک سری اتفاقات هیجان انگیز حالا وقت اون رسیده که Netlify CMS رو کانفیگ کنیم.و اما این فایل کانفیگ نمی تونه هرجایی قرار داشته باشه و یک مکان خاص میخواد.در روت پروژتون یک پوشه به نام static بسازید و داخل اون یک پوشه به نام admin بسازید و داخل admin یک فایل به نام config.yml ( اگه کنجکاو شدید که yml چیه این لینک رو بخونید )# In your static/admin/config.yml file
backend: 
name: github
repo: [YOUR-GITHUB-USERNAME]/[YOUR-REPO-NAME]
media_folder: static/assets
public_folder: assetsنام ریپو و یوزنیم گیتهابتون رو در تنظیمات جایگذاری کنید.حالا وقت اون رسیده که یکی از انواع collection ها رو برای ادامه ی پروژه انتخاب کنیم.در Netlify CMS دو جور کالکشن داریم ۱- فولدر کالکشن و ۲- فایل کالکشناما فرقشون چیه؟فولدر کالکشن بیشتر زمانی استفاده میشن که محتوای شما از یک جنس و شبیه به هم باشه ( به عنوان مثال وبلاگ که از چندین پست با یک فرمت یکسان تشکیل میشه و یا یک سایت فروشگاهی که از چندین محصول با یک فرمت یکسان تشکیل میشه )فایل کالکشن بیشتر مربوط به زمانی هست که محتوای شما منحصر به فرد هستند.در این آموزش ما از فولدر کالکشن استفاده می کنیم و کانفیگ زیر رو به فایل config.yml اضافه می کنیم :متاسفانه ویرگول تورفتگی ها رو درست نمایش نمیداد و مجبورم کدها رو اینطوری بزارم.خب و اما معنی این ها چیه؟در این نوع پیکربندی ها هرچیزی نیاز داره که یک label و name داشته باشه.چیزی که در ادمین پنل نشون داده میشه label هست و چیزی که ما توی کد باهاش به عنوان متغیر کار داریم اسمش name هست.پس ما اومدیم لیبل و نام کالکشن رو Pages گذاشتیم.نوع کالکشنمون رو با :files مشخص کردیم که از نوع فایل کالکشن هست و مجددا همونطور که بالا گفتم نیاز داریم تا لیبل و نام رو بهش اختصاص بدیم.و زیرش یکی از پیج هامون رو معرفی کردیم بهش ( همون پیجی که ابتدای مطلب مقاله ی مفهوم SSG رو مطالعه کردید )و با :fields مشخص کردیم که چه فیلد هایی رو نیاز داریم تا در ادمین پنل این پیج قرار داشته باشن ( اگه متوجه نشدید مشکلی نداره، جلوتر که بریم با چشم خیلی چیزها رو می بینیم )یک نکته ی مهم : زمانی که از فایل کالکشن استفاده می کنید دقت داشته باشید که فایلی که تعریفش می کنید حتما باید وجود داشته حتی اگه خالی باشه ( در اینجا فایلی که ما تعریف کردیم content/ssg-concept.md هست ) پس یک پوشه در روت پروژتون به نام content بسازید و داخلش یک فایل خالی به نام ssg-concept.md رو بسازید.خب همه چیز خوبه. الان به آدرس زیر برید و لاگین کنید :[YOUR-NETLIFY-SUBDOMAIN]/admin/
// for example: https://frontcampigan.netlify.com/admin/الان باید تصویر زیر رو ببینید :داشبورد ادمین پنل مدیریت محتواو با کلیک کردن روی SSG Concept به حکمت اون field ها و widget هایی که تعریف کردیم پی می برید:ویجت هایی که تعریف کردیم در فیلدهای بالا اینجا کاملا خودنمایی می کننیکی از ضعف هایی که Netlify CMS داره اینه که ادیتور قدرتمندی مثل strapi نداره.و اما شاید الان براتون این سوال پیش بیاد که اگر بخواید فیلد ها و ویجت های متنوع تری اضافه کنید باید چیکار کنید که مفتخرم عرض کنم Netlify CMS یک داکیومنت خوب داره که در این قسمت می تونید فیلد ها و ویجت های مختلف رو ببینید و استفاده کنید.وارد کردن اطلاعاتدر این مرحله فیلد های مورد نظر رو پر کنید و به روی publish کلیک کنید.خطر ذوق مرگی: پس از publish کردن به ریپوی گیتهاب خود رفته و ببینید که چطور commit جدیدی خوردهنکته ی گیتی: وقتی ریپوی شما commit جدیدی میخوره اما کد لوکال شما همچنان sync نیست باید حتما دستور زیر رو اجرا کنید تا مطابق با آخرین تغییرات ریپو پیش برید و کد بزنید :git pullپس از انجام دستور بالا به همون فایلی که در config.yml تعریف کردیم برید و میبینید که اون فایل دیگه خالی نیست !گرفتن اطلاعاتخب تجربتون تا اینجا از این استک چی بوده؟ می دونید اگر قرار بود به صورت فرانت معمولی و عادی این پروسه رو طی کنیم باید فقط چه مدت زمانی منتظر می موندیم تا به این فاز برسیم؟ پس سرعت توسعه به شکل محسوسی بالا رفتهابتدای شروع نوشتن این مقاله فکر میکردم نمی تونم انقدر تایپ کنم :|خب تا اینجا ما تونستیم اطلاعات رو از پنل ادمین به ریپوی گیتهابمون بفرستیم اما همچنان چیزی در سایتمون نمی بینیم چون به گتسبی نگفتیم که این اطلاعات و دیتا رو چطور پیدا کنه و به صفحات ما اضافه کنه.برای این که بتونیم به گتسبی بگیم چطور این اعمال رو انجام بده نیاز داریم تا دوتا از پر کاربردترین پلاگین های گتسبی رو نصب کنیم پس دستور زیر رو بزنید :npm install --save gatsby-source-filesystem gatsby-transformer-remarkما از پلاگین gatsby-source-filesystem استفاده می کنیم تا به گتسبی بگیم فایل هامون کجاست.طبق فیلد هایی که گذاشتیم و تعریف کردیم ما دو جور فایل داریم یکی فایل های markup یا همون md. و یکی هم فایل های عکسمونپس توی فایل gatsby-config.js کدهای زیر رو اضافه می کنیماگه واستون سوال پیش اومد که dirname__ چی هست باید بگم این عبارت به پوشه ای که توش این فایل رو می نویسیم برمیگرده
اولین نمونه ی کانفیگ ما در کدهای بالا به دنبال تصاویر میگرده و دومیش به دنبال فایل های markdown ای که توسط CMS ساخته میشه.همچنین در مورد gatsby-transformer-remark نقش یک parse کننده برای فایل های markdown رو داره.بریم سراغ GraphQL ؟گراف کیوال یک Query Language برای API هاست که بر خلاف REST بسیار منعطف تر و بهینه تر و قدرتمند تره که در سال ۲۰۱۲ توسط فیسبوک ساخته شده و اگه باهاش آشنایی ندارید و میخواید یک مرور سریع بهش داشته باشید از این سایت دیدن کنید و تمرین هاش رو انجام بدید و بیاید بریم سراغ ادامه ی مقاله.ما اینطوری منتظر میمونیم تا شما برید بخونید و تمرین کنید و بیاید :))چون در این مقاله قرار نیست به آموزش گراف کیوال بپردازیم می تونید تموم کوئری ها رو کپی کنید و بنویسید.یکی از ابزارهایی که گتسبی داره و به نوعی کوئری زدن رو راحت تر کرده ابزاری هست به نام GraphiQL که می تونید اون رو در آدرس زیر پیدا کنید :http://localhost:8000/___graphqlحالا ما میخوایم node ای رو پیدا کنیم که بهمون ssg-concept.md رو بده.یه راه اینه با استفاده از sourceInstance فیلتر کنیم و بگیم دقیقا چه فایلی رو میخوایم اما این راه به قول برنامه نویس ها بدبوعه و زیاد خوشایند نیست.allFile &#40;filter: {sourceInstanceName: {eq: &amp;quotcontent&amp;quot} name: {eq: &amp;quotssg-concept&amp;quot}}&#41;پس ما یک کار زیباتر انجام میدیم و با استفاده از نود childMarkdownRemark شروع به خوندن فایل های markdown می کنیم این فایل ها رو توی frontmatter و html جداسازی می کنیم.اینطوری بدنه ی فایل های Markdown از طریق html در دسترس خواهد بود و چیزهای دیگر مثل رشته ها تاریخ و .. از طریق frontmatter در دسترس خواهد بود.از اونجایی که ما در body فایل های markdown چیزی نداشتیم پس به frontmatter کوئری می زنیم: نتیجه ای که به ما برمیگرده یک object هست که حاوی مقادیری هست که میخواستیم ( نه کمتر و نه بیشتر ) این دقیقا یکی از قدرت های GraphQL هست.نمایش اطلاعاتاین دیتایی که به ما برمیگرده در props قرار میگیره و ما می تونیم ازش برای نمایش اطلاعات استفاده کنیم.نکته مهم : حواستون باشه که edges یک ارایه است و باید روش map بزنید.پی نوشت : من چون یکم به سبک ری اکت نوشتم و از کامپوننت های مختلفی استفاده کردم جهت نمایش گذاشتن کدهام شما رو گیج می کنه اما اگه بخواید می تونید آدرس گیت پروژه که در انتهای مطلب میگذارم رو بخونید و روش انتقال دیتا رو توسط من ببینید و خب حالا میریم سراغ قسمت آخر مقاله..حس دوستانی که بی وقفه تا اینجا مطالعه کردن مطلب رو :))ایجاد داینامیک صفحات با استفاده از اطلاعاتخب تا الان یک صفحه ی ایندکس خیلی قشنگ ساختیم که عنوان ، زمان مطالعه ( طبق تعداد کاراکتر می تونید با استفاده از این سایت زمان خوندن رو محاسبه کنید ) و یک خلاصه ی مقاله رو نمایش میده.اما ما نمی خوایم که فقط خلاصه یک مقاله رو بخونیم و تمایل داریم تا تموم مقاله رو بخونیم. درست مثل همون چیزی که در دمو دیدید تصمیم داریم یک صفحه ی کامل مقاله با استفاده از دیتا بسازیم.یک راهش اینه که به مسیر src/pages بریم و برای هر مقاله جداگانه یک صفحه بسازیم اما این خیلی هاردکده و از یه برنامه نویس به دوره پس ما راه دوم رو انتخاب می کنیم.راه دوم چیه؟ این که یک صفحه ی داینامیک بسازیم.مراحل ساخت یک صفحه ی داینامیک :ساخت یک مسیر یا path یا slug برای URL هر صفحهساختن صفحهساخت مسیر یا path یا slug برای URL هر صفحهاکثر Headless CMS ها این مورد رو به عنوان یک دیتا برمیگردونن و می تونید با کوئری زدن بهش دیتای مورد نظرتون رو دریافت کنید اما ما باز هم از Netlify CMS ها استفاده کردیم تا این مورد هم دستی انجام بدیم و بگیم ترسی نداره :دیبرای ساخت markdown page ها از دو API گتسبی به نام های onCreateNode و createPages استفاده می کنیم که در بسیاری از سایت ها و پلاگین ها این دو API رو مشاهده می کنید.اما برای کار با API های خود گتسبی مثل مواردی که بالا برشمردم لازمه که کانفیگ ها رو در فایلی به نام gatsby-node.js بنویسیم . پس این فایل رو در روت پروژه بسازید.سپس کد زیر رو در اون قرار بدید :exports.onCreateNode = ({ node }) =&gt; {
console.log(node.internal.type)
}خب ما از onCreateNode استفاده کردیم تا به گتسبی بگیم هر زمان یک node جدید ساخته شد و یا آپدیت شد به ما خبر بده.برای اینکه دقیق تر متوجه بشید یک بار development server رو متوقف و سپس مجدد ران کنید.حالا به ترمینال نگاه کنید و چیز هایی که لاگ انداخته شده رو ببینید.در مرحله ی بعدی ما میخوایم با استفاده از این API توسط Markdown Remark هامون به صفحات Markdown لینک بدیم و مسیر یا همون slug رو بسازیم.پس دوباره کد موجود در gatsby-node.js رو به کد زیر تغییر بدید :exports.onCreateNode = ({ node }) =&gt; {
if (node.internal.type === `MarkdownRemark`) {
console.log(node.internal.type)
}
}اما هدف صالی ما از این کار چیه؟ ما میخواهیم که اسم فایلمون اگر ssg-concept.md هست مسیر یا slug مورد نظرمون /ssg-concept/ باشه.اما بنظر شما باید چیکار کنیم تا اسم فایل markdown رو از node مورد نظرمون دریافت کنیم؟شما باید node graph رو مرور کنید و با استفاده از node-parent به نام فایل دسترسی پیدا کنید.برای این منظور فایل gatsby-node.js رو مجدد تغییر بدید:exports.onCreateNode = ({ node, getNode }) =&gt; {
if (node.internal.type === `MarkdownRemark`) {
const fileNode = getNode(node.parent)
console.log(`\n`, fileNode.relativePath)
}
}مجددا development server تون رو ری استارت کنید و در ترمینال لاگ مربوط به مسیر فایل markdown رو مشاهده می کنید.خب حالا زندگی شیرین شد نه؟ :دیالان با استفاده از gatsby-source-filesystem میایم و مسیر مدنظر برای URL هامون رو می سازیم:const { createFilePath } = require(`gatsby-source-filesystem`)
exports.onCreateNode = ({ node, getNode }) =&gt; {
if (node.internal.type === `MarkdownRemark`) {
console.log(createFilePath({ node, getNode, basePath: `pages` }))
}
}مجددا development server رو ری استارت کنید و به من بگید که لذت بخش بود یا نه؟ :)بسیار هم عالی الان شما یک مسیر دارید که باهاش می تونید به صورت داینامیک پیج بسازید و فقط لازمه که این مسیر رو به عنوان یک فیلد اضافه به node اضافه کنیم که این کار رو با createNodeField انجام میدیم پس دوباره به gatsby-node.js برید و این بار به صورت زیر ویرایشش کنید :const { createFilePath } = require(`gatsby-source-filesystem`)
exports.onCreateNode = ({ node, getNode, actions }) =&gt; {
const { createNodeField } = actions
if (node.internal.type === `MarkdownRemark`) {
const slug = createFilePath({ node, getNode, basePath: `pages` })
createNodeField({
node,
name: `slug`,
value: slug,
})
}
}پس از ری استارت کردن development server این بار ابزار GraphiQL رو باز کنید و نتیجه ی کوئری زیر رو ببینید:هووورررراااا ! شما مسیر رو ساختید ! دمتون گرم که تا اینجا اومدید.ساختن صفحاتبا استفاده از createPages API و کد زیر که در gatsby-node.js می نویسیم ( پایین تر از کدهای قبل ) به مسیر مورد نظرمون کوئری می زنیم و دوباره توی terminal  لاگ می زنیم ( یادتون نره که development server رو حتما ری استارت کنید )خب حالا ما همه ی دیتایی که می خوایم رو داریم پس کافیه که دیتامون رو map بزنیم و صفحات رو داینامیک بسازیم. برای این منظور یک template برای پست هامون می سازیم که یک کامپوننت ری اکتی هست و اون رو در مسیر src/template ایجاد می کنیم و نام دلخواهی مانند single-post.js براش انتخاب می کنیم. ( نوشتن این کامپوننت رو به سلیقه ی خودتون واگذار می کنم )و حالا این فایل رو به gatsby-node.js معرفی می کنیم و مجدد کل فایل رو بدین شکل آپدیت می کنیم :حالا development server رو ری استارت کنید و می بینید که پیجتون ساخته شده :)برای گرفتن دیتا در template post type مدنظر می تونید یه همچین کوئری ای بزنید :شما می تونید مقادیر دیگه ای رو هم بگیرید ( غیب گویی با چشمان بسته )الان صفحات شما کامل ساخته شدند :) فقط کافیه به title مقاله هاتون که در صفحه ی اصلی لیست شدند یک لینک با استفاده از Link خود گتسبی بدید و در صفحه ی اصلیتون کوئری بزنید و slug رو دریافت کنید تا به اون مسیر مورد نظر لینک بزنید.کوئری مورد نظر تقریبا یه همچین چیزی میشه ( بسته به نوع کامپوننت نویسی شما و همچنین مواردی که ممکنه کوئری بزنید قطعا متفاوت خواهد بود و کوئری زیر صرفا جهت اینه که نحوه ی کوئری زدن slug رو ببینیم ولی شما می تونید سورس کامل پروژه رو توی گیت ببینید )خط پایانرابرت دنیرو توی رفقای خوب میگه هیچوقت چغلی رفتار دوستانت رو نکن و همیشه دهنت رو بسته نگه داراما خب من توی این پست سعی کردم تا می تونم چغلی این دو رفیق رو بکنمکمی و کاستی های نگارش رو ببخشید سعی کردم خودمونی صحبت کنم تا خستتون نکنم و قطعا توی این حجم مقاله ممکنه برخی جاها براتون مبهم باشه که من با کمال میل به تمام سوالاتتون پاسخ میدم در نظرات بپرسید ازم :)سورس کامل پروژه رو می تونید از لینک زیر ببینید :https://github.com/Mvahedii/frontcampLinkedin | Github |</description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>محمد واحدی</author>
                <pubDate>Mon, 03 Feb 2020 01:49:53 +0330</pubDate>
            </item>
                    <item>
                <title>چطور logic پروژمون رو بین React و React Native باید share کنیم؟</title>
                <link>https://virgool.io/iran-react-community/%DA%86%D8%B7%D9%88%D8%B1-logic-%D9%BE%D8%B1%D9%88%DA%98%D9%85%D9%88%D9%86-%D8%B1%D9%88-%D8%A8%DB%8C%D9%86-react-%D9%88-react-native-%D8%A8%D8%A7%DB%8C%D8%AF-share-%DA%A9%D9%86%DB%8C%D9%85-ahbo66zufc2n</link>
                <description>وقتی React Native کد میزنین انتظار دارین که بعد از تموم شدن پروژه بتونین به راحتی خروجی پلتفرم Android و IOS رو بگیرین.پس حتما انتظار اینم دارین با کمترین زمان، نسخه وب پروژتون رو هم بنویسین و از همه مهم تر اینکه توسعه پروژه وب و موبایلتون در آینده به سادگی تغییر چند خط کد باشهخب اول از همه باید بدونین چه بخش هایی رو میشه بین React و React Native پروژتون share کنینConfigAPIsRedux Custom HooksForm ValidationsHelpersThemesTypescriptsبخش Configدر بخش config پروژتون base API URL، اسم پروژه و هر متغییر ثابتی که بین وب و موبایلتون مشترکه رو میتونین اینجا بنویسینبخش API هادر این بخش برای هر entity در پروژتون فایل مشخص به خودش رو بسازین و API هایی که از بچه های گل بک اند گرفتین رو اینجا تعریف کن، من در این بخش از کتابخونه Axios استفاده کردم، برای مثال یه فایل به نام auth.js ساختم و داخل اون API های لاگین و فراموشی کلمه عبور و ... رو تعریف کردم.بخش Reduxریداکس برای share کردن logic پروژتون بدون وابستگی به کامپوننت‌ها خیلی میتونه کمک کنه، میشه از روش های دیگه ای هم واسه handle کردن state هاتون استفاده کنین، ولی debug کردن state ها با ریداکس مثه آب خوردنهبخش Custom Hooksمن این بخش رو خیلی دوست دارم، بعد از اینکه هوک متولد شد، پروژه های من به طرز عجیبی ساده و خوانا تر شدن (clean code رو میزاره توی جیبش لامصب)هوک‌ها برای نوشتن logic یه کامپوننت میتونن خیلی بهتون کمک کنن، به راحتی میتونین state‌ها وlifecycle  یه کامپوننت رو از توی دل اون بکشید بیرون و در یه فایل مجزا logic اش رو برنامه نویسی کنین. برای مثال میتونین برای بخش لاگین پروژتون یه هوک به اسم useLogin بنویسین و تمام فیلدهای فرم لاگینتون رو در قالب یه state‌ تعریف کنین، همچنین میتونین  و   فرم اتون رو همینجا بنویسین، که خود  میتونه شامل validation فرم و فراخوانی API لاگینتون باشه.بخش Validation های فرمبا توجه به اینکه API هاتون بین وب و موبایل share شده، پس تمام attribute های entity پروژتون بین React و React Native مشترکه و از طرفی تمام فیلدهاتون در فرم مشترک میشه، خب پس میتونین validation های فرم تون رو یه جا بنویسین و اونا رو share کنین (من از کتابخونه Yup برای نوشتن validation هام استفاده میکنم)بخش Helper هادر این بخش میتونین توابع کمکی پروژتون رو بنویسین، برای مثال توابعی که نیازه روی string یا array هاتون فیلتر خاصی اعمال کنین، یه helper خیلی مهم که من توی پروژم باهاش درگیر شدن، هلپری واسه storage بود، این هلپر رو نمیشه بیرون share نوشت واسه اینکه redux و hook هاتون بهش احتیاج دارن، پس با یه کلک مرغابی میتونین همه جا یک جور import هاتون رو بنویسین ولی در صورتی که چیزی که دارین import میکنین، webpack با توجه به پلتفرم مورد نظر فایل خودش رو داره فراخوانی میکنهدر بخشhelpers  یه دایرکتوری به اسم storage بسازین و سه تا فایل زیر رو اونجا قرار بدینIndex.android.jsIndex.ios.jsIndex.jsدرون دو فایل اول که React Native با توجه به پلتفرم اونا رو فراخوانی می‌کنه از کتابخانه @react-native-community/async-storage استفاده کنین و در فایل آخر که برای وب عه از localStorage استفاده کنین.بخش Themeاگر پروژتون شامل چندین theme مختلف عه میتونین پالت رنگ و فونت هاتون رو اینجا تعریف کنینبخش Typescriptاگه از تایپ اسکریپت هم استفاده می‌کنین که type و interface هاتون رو اینجا تعریف و export کنینحالا ممکنه واستون سوال بشه که این بخش هارو کجای پروژه وب و موبایلتون باید قرار بدیناین بخش رو مثل یه ریپو مجزا فرض کنین، برای مثال یه repository به اسم share در گیت لب و یا گیت هاب خودتون بسازین و در root پروژه وب و موبایلتون از اون clone بگیرینچند تا نکته ریز:-	توی پروژه وب و موبایلتون در فایل gitignore دایرکتوری share که در root پروژتون هست رو ignore کنین، چون share خودش یه ریپو مستقله، و اگه تغییری روش دادین به صورت مستقل باید تغییراتش رو commit کنین-	نیازی به package.json واسه پروژه share نیست، چون این repository در root پروژه وب و موبایلتون قرار میگیره و از package.json اون‌ها استفاده میکنه-	پکیج هایی که در بخش‌های share استفاده کردین رو در فایل README لیست کنین تا برنامه‌نویس  وب و موبایلتون پکیج های پروژه share رو روی پروژه خودش نصب کنه</description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>جواد مسعودیان</author>
                <pubDate>Fri, 10 Jan 2020 16:45:09 +0330</pubDate>
            </item>
                    <item>
                <title>الگوهای ری اکت - ۴</title>
                <link>https://virgool.io/iran-react-community/%D8%A7%D9%84%DA%AF%D9%88%D9%87%D8%A7%DB%8C-%D8%B1%DB%8C-%D8%A7%DA%A9%D8%AA-%DB%B4-upmhchksvro3</link>
                <description>تو این مقاله که آخرین قسمت از سری الگوهای ری اکت هست، میخوام در مورد بهترین روش های استفاده از امکانات و قدرت ری اکت صحبت کنم. استفاده از الگوهای ری اکت باعث میشه کدهایی بنویسیم که به لحاظ کارایی و خوانایی سطح بالاتری داشته باشند.تو این مقاله قصد دارم الگوهای ری اکت رو با بیان ساده شرح بدم . این مقاله برداشت آزادی از سایت الگوهای ری اکت است.برای مطالعه قسمت های قبلی: http://vrgl.ir/u1wC0  http://vrgl.ir/3hD8V  http://vrgl.ir/Ahf19 سرفصل های این قسمت:Container component , Higher-order component, State hoisting, Controlled inputالگوهای ری اکتاستفاده از Container componentقبل از هر چیز، نگاهی به تعریف کانتینر داشته باشیم:کانتینر ، وظیفه گرفتن دیتا و رندر کردن کامپوننت های مربوطه رو داره.کامپوننت CommentList زیر رو در نظر بگیرید که با مپ زدن روی لیستی از کامنت ها، اسم نویسنده و متن نوشته شده رو نمایش میده:const CommentList = ({ comments }) =&gt; (
  &lt;ul&gt;
    {comments.map(comment =&gt; (
      &lt;li&gt;
        {comment.body}-{comment.author}
      &lt;/li&gt;
    ))}
  &lt;/ul&gt;
);می‌تونیم کانتینر جدیدی بنویسیم که وظیفه گرفتن اطلاعات و همچنین رندر کردن اونها رو داشته باشه. تو تکه کد زیر از ajax برای درخواست زدن به سرور استفاده شده. (البته می‌تونید از fetch  و  axios استفاده کنید)class CommentListContainer extends React.Component {
  state = { comments: [] }
  componentDidMount() {
    $.ajax({   // اینکه اینجا چه اتفاقی داره می‌افته مهم نیست
      url: &amp;quot/my-comments.json&amp;quot,
      dataType: &#039;json&#039;,
      success: comments =&gt;
        this.setState({comments: comments});
    })
  }

  render() {
    return &lt;CommentList comments={this.state.comments} /&gt;
  }
}
با لود شدن این کامپننت، درخواست Ajax زده می‌شه و داده ها به استیت کامپوننت CommentListContainer فرستاده میشه .داده های این state به کامپوننت CommentList داده میشه تا اونجا رندر بشه.استفاده از Higher-order component قبل از هر چیز،‌ نگاهی به تعریف تابع مرتبه بالا داشته باشیم:تابعی که تابع دیگری در ورودی می‌گیره و یا تابعی رو برمی‌گردونهکامپوننت مرتبه بالا چیه؟کامپوننت Greeting رو در نظر بگیرید:const Greeting = ({ name }) =&gt; {
  if (!name) {
    return &lt;div&gt;Connecting...&lt;/div&gt;;
  }
  return &lt;div&gt;Hi {name}!&lt;/div&gt;;
};
اگر این کامپونننت، پراپسی به اسم name بگیره، اون اسم رو همراه با کلمه &quot;سلام&quot; به نمایش میزاره در غیر این صورت عبارت Connecting... رندر میشه.حالا چه جوری کامپوننت مرتبه بالا رو پیاده سازی کنیم؟const Connect = ComposedComponent =&gt;
  class extends React.Component {
    constructor() {
      super();
      this.state = { name: &amp;quot&amp;quot };
    }

    componentDidMount() {
      // this would fetch or connect to a store
      this.setState({ name: &amp;quotMichael&amp;quot });
    }

    render() {
      return &lt;ComposedComponent {...this.props} name={this.state.name} /&gt;;
    }
  };
  تابع Connect کامپوننت ComposedComponent رو برمی‌گردونه. این کامپوننت، Name که به عنوان آرگومان بهش پاس می‌دیم رو می‌گیره (که اینجا Michael هست) و رندر می‌کنه. آخرین قدم، قرار دادن کامپوننت Greeting در تابع Connect که قبلا نوشتیم ( به این کار می‌گیم رپ کردن). در نتیجه قبل از لود شدن کامپوننت، رو صفحه عبارت Connecting...  و بعد از لود شدن صفحه عبارت Hi Michael نمایش داده می‌شود.const ConnectedMyComponent = Connect(Greeting);این یکی از قدرتمندترین الگوها برای گرفتن اطلاعات و پاس دادنش به کامپوننت های تابعی هست.استفاده از State hoistingکامپوننت های تابعی بر خلاف کلاس کامپوننت ها نمی‌تونن state داشته باشند ( تا قبل از اومدن ری اکت هوک این شکلی بود اما الان دیگه این جوری نیست)‌. به کامپوننت Name دقت کنید. تابع  به صورت پراپس به این کامپوننت پاس داده می‌شه. توی کامپوننت پدر هم این مقدار رو به  پاس میدیم. به این کار state hoisting گفته می‌شه.class NameContainer extends React.Component {
  render() {
    return &lt;Name ={newName =&gt; alert&#40;newName&#41;} /&gt;;
  }
}

// کامپوننت اسم که به صورت فانکشنال نوشته شده
const Name = ({  }) =&gt; (
  &lt;input ={e =&gt; (e.target.value)} /&gt;
);مثال پایین که در واقع همون مثال کامل شده بالا هست به ما نشون میده که به چه سادگی می‌تونیم تغییرات استیت رو با کامپوننت Name که داشتیم همراه کنیم:class NameContainer extends React.Component {
  constructor() {
    super();
    this.state = { name: &amp;quot&amp;quot };
  }

  render() {
    return &lt;Name ={newName =&gt; this.setState({ name: newName })} /&gt;;
  }
}در واقع state بجای اینکه توی کامپوننت Name باشه، به کانتینرش رسید. اینجوری به راحتی کامپوننت فانکشنالی نوشتیم که استیت نداره (ولی از طریق کانتینر بهش استیت دادیم) و بدون در نظر گرفتن مقدار  همه جا کار می‌کنه !در آخر توضیح این نکته ضروری هست که این الگو ، محدود به فانکشال کامپوننت نیست و به راحتی با کلاس کامپوننت ها قابلیت پیاده سازی داره.استفاده از Controlled inputکامپوننت ساده و uncontrolled زیر رو در نظر بگیرید:&lt;input type=&amp;quottext&amp;quot /&gt;می‌خواهیم این کامپوننت رو به کامپوننت Controlled تبدیل کنیم. با نوشتن state این کارو شروع می‌کنیم:class ControlledNameInput extends React.Component {
  constructor() {
    super();
    this.state = { name: &amp;quot&amp;quot };  // قرار دادن یک اسم خالی برای نمایش مقدار اولیه 
  }

  render() {
    return &lt;input type=&amp;quottext&amp;quot value={this.state.name} /&gt;;
  }
}خوب تنها کاری که باید انجام بدیم، قرار دادن تابع  هست که وظیفه تغییر state  رو داره:return (
  &lt;input
    value={this.state.name}
    ={e =&gt; this.setState({ name: e.target.value })}
  /&gt;
);این ۴ نوشته با اسم الگوی ری اکت همین جا به پایان می‌رسه، سعی کردم با بیانی ساده بنویسم. با گفتن نظراتون به بهتر شدن نوشته هام کمک کنید. ممنونسایر مقاله های من در ویرگول: http://vrgl.ir/YhkrX  http://vrgl.ir/JgETy  http://vrgl.ir/aE7sU Follow me on social mediaTelegram Facebook Twitter Linkedin Virgool</description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>Nima Mohamadian</author>
                <pubDate>Wed, 01 Jan 2020 11:20:21 +0330</pubDate>
            </item>
                    <item>
                <title>کانفیگ Context با typescript</title>
                <link>https://virgool.io/iran-react-community/%DA%A9%D8%A7%D9%86%D9%81%DB%8C%DA%AF-context-%D8%A8%D8%A7-typescript-esg7ctaphwmb</link>
                <description>چند وقتیه که به صورت مستمر پیگیر ری‌اکتم . تا حالا دنبال تایپ‌اسکریپت نرفته بودم و تا اینکه دلو زدم به دریا و رفتم سراغش . در کمال ناباوری دیدم چقد خفنه و چقد کد رو تمیز میکنه . تصمیم گرفتم یه مقاله بنویسم و یه توضیحاتی راجبه کانفیگ کانتکست با تایپ‌اسکریپت بدم و باهم یه todolist ساده با قابلیت اضافه کردن todo بزنیم .خب  اول از همه باید ts رو به پروژه اضافه کنیم با دستور npm install --save typescript @types/node @types/react @types/react-dom @types/jest خب میریم سراغه تعریف type و interface ها . میتونید همه رو تو یه فایلی مثلا به اسمه types.ts بریزید و یا تو هر کامپوننت اینترفیس تعریف کنید. حالا من همرو جدا کردم تو یه فایل به اسمه types.ts : خب یک فایلی به نام Context.tsx میسازیم و توی اون کانتکستمونو قرار میدیم :‌همونطور که میبینید تایپ کانتکست یه آرایه ای از اینترفیس ITodo هست . بنابراین با اینکار provider و consumer هم تایپشون یکی میشه . خب حالا initialState چیه ؟ اینه :  قبله این که بریم سراغ reducer یکسری interface برای اکشن ها تو فایله types.ts ست میکنیم :همونجور که معلومه یه اینترفیس پایه برای اکشن در نظر گرفتیم و هر اکشن با توجه به payload از اون extend میشه . و در آخر یه تایپ تعریف میکنیم که همه اکشن هایی که داریم رو با هم or میکنه (حالا اینجا یکی بیشتر نیس و اونم ContextAddTodoAction هست ) خب میریم سراغه همون فایله Context.tsx و شرو میکنیم به نوشتن reducer و provider از useReducer اینجور استفاده میکنیم :‌تو قسمته React.Reducer ، دوتا پارامتر برا تایپ داریم ، اولی تایپه استیتمون هست که یه آرایه از ITodo هاست و دومی هم تایپ اکشن هامونه ک قبلا با هم or شده بودن . و reducer هم به این شکل:و provider نیز : خب اینجا یه مشکلی پیش میاد و اونم اینه که وقتی ما تایپه اولیه کانتکست رو گذاشتیم [ ]ITodo ، تایپ provider هم باید [ ]ITodo باشه . ولی همونجور ک میبینید تایپ value یه آبجکته .برای حل این مشکل کافیه تایپه کانتکستمونو عوض کنیم و این ریختی شه :‌تایپه کانتکست شد یه آبجکت که یه todos داره و یه dispatch . ورودی dispatch یه action هست و این تابع چیزی بر نمیگردونه void و مقدار اولیش هم یه فانکشن خالی میذاریم . حالا فقط کافیه context رو export کنیم :‌تمامم !!!</description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>Ali Sajadi</author>
                <pubDate>Sun, 22 Dec 2019 22:00:36 +0330</pubDate>
            </item>
                    <item>
                <title>الگو‌های ری اکت - ۳</title>
                <link>https://virgool.io/iran-react-community/%D8%A7%D9%84%DA%AF%D9%88%D9%87%D8%A7%DB%8C-%D8%B1%DB%8C-%D8%A7%DA%A9%D8%AA-%DB%B3-w1hxrbf4buho</link>
                <description>تو این مقاله می‌خوام در مورد بهترین روش های استفاده از امکانات و قدرت ری اکت صحبت کنم. استفاده از الگوهای ری اکت باعث میشه کدهایی بنویسیم که به لحاظ کارایی و خوانایی سطح بالاتری داشته باشند.تو این مقاله قصد دارم الگوهای ری اکت رو با بیان ساده شرح بدم . این مقاله برداشت آزادی از سایت الگوهای ری اکت است.برای مطالعه قسمت های قبلی: http://vrgl.ir/u1wC0  http://vrgl.ir/3hD8V سرفصل های این قسمت:Proxy components, Style component, Event switch, Layout componentالگوهای ری کتاستفاده از Proxy componentدکمه ها همه جا توی وب اپلیکیشن ها هستند. معمولا برای نوشتن یک دکمه از کد زیر استفاده می‌کنیم:&lt;button type=&amp;quotbutton&amp;quot&gt;اینکه بیایم برای همه دکمه ها از صفت  type و نوع button استفاده کنیم کار درستی نیست ( احتمال وجود خطا رو افزایش میده)  به جاش از یک کامپوننت مرتبه بالاتر استفاده می‌کنیم:const Button = props =&gt;
  &lt;button type=&amp;quotbutton&amp;quot {...props}&gt;خوب حالا به راحتی می‌شه کامپوننت Button رو هرجایی که خواستیم استفاده کنیم و خیالمون راحت باشه که صفت type همه دکمه ها همواره button هستش.&lt;Button /&gt;
// &lt;button type=&amp;quotbutton&amp;quot&gt;&lt;button&gt;

&lt;Button className=&amp;quotCTA&amp;quot&gt;Send Money&lt;/Button&gt;
// &lt;button type=&amp;quotbutton&amp;quot class=&amp;quotCTA&amp;quot&gt;Send Money&lt;/button&gt;استفاده از  Style componentمثل پروکسی کامپوننت ، اما این بار با طعم استایل!یک دکمه داریم که می‌خواهیم با کلاس primary اون رو نمایش بدیم:&lt;button type=&amp;quotbutton&amp;quot className=&amp;quotbtn btn-primary&amp;quot&gt;خب، برای نمایش این دکمه می‌تونیم از چندین روش استفاده کنیم:import classnames from &amp;quotclassnames&amp;quot

const PrimaryBtn = props =&gt; &lt;Btn {...props} primary /&gt;;

const Btn = ({ className, primary, ...props }) =&gt; (
  &lt;button
    type=&amp;quotbutton&amp;quot
    className={classnames(&amp;quotbtn&amp;quot, primary &amp;&amp; &amp;quotbtn-primary&amp;quot, className)}
    {...props}
  /&gt;
);نکته:  ماژول classnames به ما کمک می‌کنه که از چندتا کلاس ( استایل ) استفاده کنیم و بتونیم استایل های مختلف رو باهمدیگه ترکیب کنیم.به صورت تصویری می‌تونیم ببینیم که :PrimaryBtn()
  ↳ Btn({primary: true})
    ↳ Button({className: &amp;quotbtn btn-primary&amp;quot}, type: &amp;quotbutton&amp;quot})
      ↳ &#039;&lt;button type=&amp;quotbutton&amp;quot class=&amp;quotbtn btn-primary&amp;quot&gt;&lt;/button&gt;&#039;درنهایت این ۳ تا کامپوننت که می‌بینید یکی هستند:&lt;PrimaryBtn /&gt;
&lt;Btn primary /&gt;
&lt;button type=&amp;quotbutton&amp;quot className=&amp;quotbtn btn-primary&amp;quot /&gt;این روش کمک می‌کنه که نگه داری استایل ها تو کامپوننت ساده تر باشه.استفاده از Event switchمعمولا زمانی که تابع handler می‌نویسیم ، اسم کاری که می‌خواهیم انجام بدیم رو هم اضافه می‌کنیم، مثل این تابع که اسم کلیک کردن رو بهش اضافه کردیم:handleClick(e) { /* do something */ }برای کامپوننتی که چندین رویداد مختلف رو مدیریت می‌کنه، این اسم تابع می‌تونه تکراری باشه:handleClick() { require(&amp;quot./actions/doStuff&amp;quot)(/* action stuff */) }
handleMouseEnter() { this.setState({ hovered: true }) }
handleMouseLeave() { this.setState({ hovered: false }) }‌می‌تونیم یک تابع handler داشته باشیم و از switch / case کمک بگیریم:handleEvent({type}) {
  switch(type) {
    case &amp;quotclick&amp;quot:
      return require(&amp;quot./actions/doStuff&amp;quot)(/* action dates */)
    case &amp;quotmouseenter&amp;quot:
      return this.setState({ hovered: true })
    case &amp;quotmouseleave&amp;quot:
      return this.setState({ hovered: false })
    default:
      return console.warn(`No case for event type &amp;quot${type}&amp;quot`)
  }
}همچنین برای کامپوننت های ساده می‌تونیم به جای نوشتن تابع handler  ، از خود اکشن به همراه arrow function استفاده کنیم. مثال زیر نحوه انجام این کار  رو نشون میده :&lt;div ={() =&gt; someImportedAction({ action: &amp;quotDO_STUFF&amp;quot })}استفاده از Layout componentبعضی از کامپوننت ها وظیفه صفحه بندی (‌لایه های سایت و ...  ) رو به عهده دارند. ازونجایی که این سبک کامپوننت ها، المنت های استاتیک DOM  رو تشکیل میدهند پس لازم نیست که دائم در حال آپدیت شدن باشند.کامپوننتی رو در نظر بگیرید که دوتا  children  رو در کنار هم رندر می‌کنه:&lt;HorizontalSplit
  leftSide={&lt;SomeSmartComponent /&gt;}
  rightSide={&lt;AnotherSmartComponent /&gt;}
/&gt;خب ، می‌خواهیم این کامپوننت رو بهینه کنیم ( چون کارش استایل دهی و لایه بندی صفحه هست ، نیازی نیست که دائم در حال آپدیت شدن باشه).ما می‌تونیم بدون اینکه لایف سایکل کامپوننت های فرزند رو تغییر بدیم، اجازه ندیم که کامپوننت پدر آپدیت شه:class HorizontalSplit extends React.Component {
  shouldComponentUpdate() {
    return false;
  }

  render() {
    return (
      &lt;FlexContainer&gt;
        &lt;div&gt;{this.props.leftSide}&lt;/div&gt;
        &lt;div&gt;{this.props.rightSide}&lt;/div&gt;
      &lt;/FlexContainer&gt;
    );
  }
}قسمت آخر این نوشته: https://virgool.io/@novonimo/الگوهای-ری-اکت-۴-upmhchksvro3 سایر مقاله های من در ویرگول: http://vrgl.ir/fxVu0  http://vrgl.ir/j6dgK  http://vrgl.ir/GaRXJ Follow me on social mediaTelegram Facebook Twitter Linkedin Virgool</description>
                <category>جامعه توسعه دهندگان ری‌اکت ایران</category>
                <author>Nima Mohamadian</author>
                <pubDate>Sun, 22 Dec 2019 11:11:18 +0330</pubDate>
            </item>
            </channel>
</rss>