{"componentChunkName":"component---src-templates-docs-js","path":"/docs/thinking-in-react.html","result":{"data":{"markdownRemark":{"html":"<p>به عقیده ما، ری‌اکت بهترین راه برای ساخت وب اپلیکیشن هایی سریع و بزرگ، با استفاده از جاوااسکریپت است و برای ما در فیسبوک و اینستاگرام خیلی خوب جواب داده است.</p>\n<p>ری‌اکت بخش‌های خیلی خوب زیادی دارد، اما یکی از بهترین آنها، چگونگی نگرش به اپ‌هایی است که مشغول به ساخت آنها هستید.\nدر این سند (Document)، به فرایند تفکر در ساخت یک جدول محصولات با قابلیت جستجو خواهیم پرداخت، و برای ساخت این جدول از ری‌اکت استفاده میکنیم.</p>\n<h2 id=\"start-with-a-mock\"><a href=\"#start-with-a-mock\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>شروع با یک مدل  </h2>\n<p>تصور کنید که ما از قبل یک JSON API و یک مدل، که توسط طراح آماده شده است را داریم. مدل آماده شده چیزی شبیه به این است:</p>\n<p>\n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 228px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 121.42857142857144%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAYCAIAAAB1KUohAAAACXBIWXMAABYlAAAWJQFJUiTwAAACZUlEQVQ4y4VU23KqQBD0/z8nL0bjJeId8aggctOggmDQIypKFIVNy6ZSpiKkH6aWWXpnenZmM4SQKIqud7g8AvzkFzJguq673+89z4M9HA4fP+H7Pix2f/Nv5OVyaRgG7Gq12m635BFOpxPiPyDjbHAcx/FibDYb2OPxCLvb7fYx8APiB0GAU7CgWdzI2EPker3e6XQURanVao1GAwt42u02bKvVYllWVVWe5yuVCn5AmjcyLRhNA+dhHYYh9VALZxgjivG9+CLLsowjNU2zbZt6kSSyGI/Hi8WCJONGFkUxm81yHIdUqRdCms3mYDDA1h9kRNB1HWGhSo8hCAKCT6dTOO91PSAj51wu1+v1EKdYLHa7XeSMT9RpOBz+QZ7NZvP5HDl/i8QNgTaZTHAc1fKQn6HlAR85j0Yjmic04yA4kblpmmlk1FkUhImmqYoiiSKaAJFRP/ghHneTVjDTtkfTqWIYqmFopnmNew5MSICcJMFfZNLpkNdX0mwShokYBva/rrc5TpYk3Ba0pKVNLIugqiiMphH8qmmnw+FN1y3LgmBMSxq5VK0+vbxUOS7PMBWWLaM/Wq0UqT/IK8cxZjPn/d00DKzXjmNbFgbwvs+T21OS+jyvyvIYZRdFSZZHolgoFDBStEnT0j5igm17vdt9XC62aTrLJd4WCMaEr9drrFOrXauR52dSKKDmEcsSz1u5bpVhELzf76Nhkzr8Rg48L/R94rrRdntGnOv1fD7TmHhM0H94QBIjC5iHUukfz/eHw3nc23go0GHlchkTks/nISExMkrqx8DjRL3wBDHOMZKu7ROsMUWkc+uRSQAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"Mockup\"\n        title=\"\"\n        src=\"/static/1071fbcc9eed01fddc115b41e193ec11/d4770/thinking-in-react-mock.png\"\n        srcset=\"/static/1071fbcc9eed01fddc115b41e193ec11/65ed1/thinking-in-react-mock.png 210w,\n/static/1071fbcc9eed01fddc115b41e193ec11/d4770/thinking-in-react-mock.png 228w\"\n        sizes=\"(max-width: 228px) 100vw, 228px\"\n      />\n    </span>\n  </span>\n  </p>\n<p>و JSON API هم داده‌هایی را باز می‌گرداند که به صورت زیر است:</p>\n<div class=\"gatsby-highlight\" data-language=\"text\"><pre class=\"gatsby-code-text\"><code class=\"gatsby-code-text\">[\n  {category: &quot;Sporting Goods&quot;, price: &quot;$49.99&quot;, stocked: true, name: &quot;Football&quot;},\n  {category: &quot;Sporting Goods&quot;, price: &quot;$9.99&quot;, stocked: true, name: &quot;Baseball&quot;},\n  {category: &quot;Sporting Goods&quot;, price: &quot;$29.99&quot;, stocked: false, name: &quot;Basketball&quot;},\n  {category: &quot;Electronics&quot;, price: &quot;$99.99&quot;, stocked: true, name: &quot;iPod Touch&quot;},\n  {category: &quot;Electronics&quot;, price: &quot;$399.99&quot;, stocked: false, name: &quot;iPhone 5&quot;},\n  {category: &quot;Electronics&quot;, price: &quot;$199.99&quot;, stocked: true, name: &quot;Nexus 7&quot;}\n];</code></pre></div>\n<h2 id=\"step-1-break-the-ui-into-a-component-hierarchy\"><a href=\"#step-1-break-the-ui-into-a-component-hierarchy\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>قدم اول: رابط کاربری را به یک سلسله از کامپوننت‌ها تقسیم کنید</h2>\n<p>اولین کاری که باید انجام دهید، این است که دور هر کدام از کامپوننت‌های موجود خط بکشید و تمامی کامپوننت‌ها را به همراه زیرمجموعه‌های آن (subcomponents) مشخص کنید و برای هر کدام یک نام در نظر بگیرید (هر کامپوننت ممکن است یک یا چند کامپوننت زیرمجموعه داشته باشد).</p>\n<p>اگر به همراه یک طراح کار می‌کنید، ممکن است او قبلا همین کار را انجام داده باشد. نام‌گذاری آن‌ها برای لایه‌های مختلف در فایل فتوشاپی که تهیه کرده‌اند، می‌تواند نام کامپوننت‌ها در کد شما هم باشد!</p>\n<p>اما چطور بفهمیم که یک بخش باید تبدیل به یک کامپوننت جداگانه شود؟ در این موارد بهتر است از همان تکنیک‌هایی استفاده کنیم که زمان تصمیم‌گیری برای تعریف یک تابع یا یک شیء جدید به کمک‌‌‌ ما می‌آمدند.\nیکی از این تکنیک‌ها <a href=\"https://en.wikipedia.org/wiki/Single_responsibility_principle\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">اصل مسئولیت واحد (single responsibility principle)</a> است.\nاین اصل بیان می‌کند که هر کامپوننت، باید در حالت ایده‌آل فقط یک کار را انجام دهد و اگر وظایف آن گسترش یافت، باید برای آن کامپوننت‌های زیرمجموعه تعریف کرد و وظایف اضافی را به آنها سپرد.</p>\n<p>از آن‌جایی که اغلب یک مدل داده JSON به کاربر نشان داده می‌شود، متوجه خواهید شد که اگر این مدل درست ساخته شده‌باشد، رابط کاربری و ساختار کامپوننت‌های شما هم به درستی قابل ترسیم و تعیین خواهد بود.\nاین بدان دلیل است که مدل داده (data model) و رابط کاربری معمولا از یک معماری اطلاعات (information architecture) یکسان تبعیت می‌کنند.\nرابط کاربری را طوری به کامپوننت‌های مختلف تقسیم کنید که هر کامپوننت با بخش خاصی از مدل داده مرتبط باشد.</p>\n<p>\n  <span\n    class=\"gatsby-resp-image-wrapper\"\n    style=\"position: relative; display: block;  max-width: 275px; margin-left: auto; margin-right: auto;\"\n  >\n    <span\n      class=\"gatsby-resp-image-background-image\"\n      style=\"padding-bottom: 116.1904761904762%; position: relative; bottom: 0; left: 0; background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAXCAIAAACEf/j0AAAACXBIWXMAABYlAAAWJQFJUiTwAAADjklEQVQ4y32UaXOjOBCG5///mZ1PM9lsbMcXvsExxge+MPbY5pIQCCTOHuFM1klt1cKDqqXiVR+0+AbiKjOArBr/H/hEtVJ+ExanxHY5wsxDAl6B/wPirscEnscsh0dBCGVSiUnAAlomacqTjPH0K4kgZkmS5kUJeVEFyhJAfgLAKzENE+Szk2k4tm1ZtzAMREhlUYgH7pYg4bzKr6zEPAWffIiDkAVRTikRSoyRT3xBFFGxizACMfo4pCHj7D5GX8WEB0FBkD9T1KW2Xi30N0VdLzf6aiuPp8KeyjPzcNrqe3mkLLUlpYXvp+/iHNNAtbDuoSONtz7Z+sE+CNcu2mBi0Ggf0ENA9yQUi8IwQrpwA4dQAFGwIsMgwr39ePnRkBraei6yyiEfKP1a+0VdzzLIWMk48ARE3iLkhAL1CwfyTIhzr7idGB9t9ur5Mt4d9pjojreynOnxpNseAUBliQHeEdMzpG7uQpFWnhHYS4S+//wpyZO61H1qNBqSJIznVlNeaGGWeVGE4ljgxTGJ2C6hTuFCnv7x7J+OW13X5uqbolzOZyiL2VRZzOfyZHzY79KEi9rHEY2jkMUscH/h5Ca8Vp7d0mJb/VenZXZam3+ePWUCp+NRTLtto9WM9RVcznA2Pzjxo45S648YgYU360G9pvZ743ZTHQ4gIItOW2s114MeEB8cG1znjg2exy+Hh9gBu1gt4O8naDag9gLPTzAZHXqS0Zd2nbanzYW4vF7gdr1j8fPuIXbBIsbBrddCqRv0pLDVpOvV21xV3qbyVDHMYxhRLNouEO3mkzB0vcvnsO05xs/dbn04bIxGjfH4ddC3bLtqZtEKWUY5i0TNEk4TLu5DHtuPape3m3XtjwZjeSLP3maaJquzvjyZLjRFm+/OJxRRJyBuGAi8kF59C2X2u2chtuLDbtXr7qeypa+XUvesyGq9tm63Vq1XZ70EJF65gW2BfQPHuef88amc0ioOO/j+F7w2oPkK4xFgbzMaKvWaPuhrnVZqXQEjsQUgFzBm1+OXgiWbVSR1smEv7UvRsAemcei09NeaIbWNbis/7uF8/MDk5uM7VzlT8yj3B7OJvFksieuJU7CdqauJshxPFuOJOPHVuRCnI2bAM+5eUdVheSW28wtiN983PWwgZPjkhH0T+SYmJ/RufIJgU7jycvtebfG/SQkvHjAxlkFl5J/Wxcq/FKTIiPiB/gZ6RfG+cqwoSwAAAABJRU5ErkJggg=='); background-size: cover; display: block;\"\n    >\n      <img\n        class=\"gatsby-resp-image-image\"\n        style=\"width: 100%; height: 100%; margin: 0; vertical-align: middle; position: absolute; top: 0; left: 0; box-shadow: inset 0px 0px 0px 400px white;\"\n        alt=\"Component diagram\"\n        title=\"\"\n        src=\"/static/eb8bda25806a89ebdc838813bdfa3601/6b2ea/thinking-in-react-components.png\"\n        srcset=\"/static/eb8bda25806a89ebdc838813bdfa3601/65ed1/thinking-in-react-components.png 210w,\n/static/eb8bda25806a89ebdc838813bdfa3601/6b2ea/thinking-in-react-components.png 275w\"\n        sizes=\"(max-width: 275px) 100vw, 275px\"\n      />\n    </span>\n  </span>\n  </p>\n<p>در این تصویر می‌بینید که ما پنج کامپوننت در برنامه خود داریم و اطلاعاتی که هر کامپوننت نمایش می‌دهد را با حروف ایتالیک مشخص کرده‌ایم:</p>\n<ol>\n<li><strong><code class=\"gatsby-code-text\">FilterableProductTable</code> (نارنجی):</strong> شامل تمام برنامه </li>\n<li><strong><code class=\"gatsby-code-text\">SearchBar</code> (آبی):</strong> <em>ورودی‌های کاربر</em> را دریافت می‌کند</li>\n<li><strong><code class=\"gatsby-code-text\">ProductTable</code> (سبز):</strong> تمامی <em>مجموعه اطلاعات</em> را با توجه به <em>ورودی کاربر</em> نمایش داده و اطلاعات را فیلتر میکند</li>\n<li><strong><code class=\"gatsby-code-text\">ProductCategoryRow</code> (فیروزه ای):</strong> یک تیتر را برای هر <em>دسته</em> نمایش می‌دهد</li>\n<li><strong><code class=\"gatsby-code-text\">ProductRow</code> (قرمز):</strong> یک ردیف را برای هر <em>محصول</em> نمایش می‌دهد</li>\n</ol>\n<p>اگر نگاهی به کامپوننت <code class=\"gatsby-code-text\">ProductTable</code>بیندازید، متوجه میشوید که تیترهای جدول (شامل “Name” و “Price”) کامپوننت جداگانه‌ای ندارند که بیشتر یک موضوع سلیقه‌ای است و دلایل و استدلال‌هایی برای استفاده یا عدم استفاده از یک کامپوننت جداگانه برای آنها وجود دارد.\nدر این مثال، آن را بخشی از <code class=\"gatsby-code-text\">ProductTable</code> قرار دادیم، چرا که جزئی از <em>مجموعه داده ها data collection</em> بوده و رندر کردن آن وظیفه <code class=\"gatsby-code-text\">ProductTable</code> است.\nبا این حال، اگر header جدول پیچیده‌تر شود (مثلا اگر گزینه‌ای برای مرتب کردن لیست محصولات اضافه می‌کردیم)، مطمئنا منطقی‌تر بود که آنها در یک کامپوننت جداگانه با نام <code class=\"gatsby-code-text\">ProductTableHeader</code> بگذاریم.</p>\n<p>حالا که کامپوننت‌های موجود در پروژه را مشخص کردیم، وقتش رسیده که سلسله مراتب آنها را نیز تعیین کنیم. کامپوننت‌هایی که با توجه به مدل، درون یک کامپوننت دیگر قرار می‌گیرند، فرزند آن محسوب می‌شوند:</p>\n<ul>\n<li>\n<p><code class=\"gatsby-code-text\">FilterableProductTable</code></p>\n<ul>\n<li><code class=\"gatsby-code-text\">SearchBar</code></li>\n<li>\n<p><code class=\"gatsby-code-text\">ProductTable</code></p>\n<ul>\n<li><code class=\"gatsby-code-text\">ProductCategoryRow</code></li>\n<li><code class=\"gatsby-code-text\">ProductRow</code></li>\n</ul>\n</li>\n</ul>\n</li>\n</ul>\n<h2 id=\"step-2-build-a-static-version-in-react\"><a href=\"#step-2-build-a-static-version-in-react\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>قدم دوم: یک نسخه ایستا (Static) در ری‌اکت بسازید </h2>\n<p data-height=\"600\" data-theme-id=\"0\" data-slug-hash=\"BwWzwm\" data-default-tab=\"js\" data-user=\"lacker\" data-embed-version=\"2\" class=\"codepen\">این بخش را در <a href=\"https://codepen.io/gaearon/pen/BwWzwm\">فکر کردن در چارچوب ری‌اکت: گام دوم</a> روی <a href=\"https://codepen.io\">CodePen</a> ببینید.</p>\n<script async src=\"https://production-assets.codepen.io/assets/embed/ei.js\"></script>\n<p>بعد از اینکه سلسله مراتب را مشخص کردید، نوبت به پیاده‌سازی اپ می رسد. راحت‌ترین راه این است که نسخه‌ای بسازید که مدل داده ها را می‌گیرد و رابط کاربری را تولید می‌کند اما هیچ تعاملی با کاربر ندارد.\nبهتر است که این دو فرایند (نوشتن نسخه تعاملی و ایستا) را از هم جدا کنیم، به این دلیل که ساخت نسخه ایستا، به مقدار زیادی نوشتن و مقدار کمی فکر کردن نیاز دارد. اما اضافه کردن امکان تعامل و پویایی، احتیاج به مقدار زیادی تفکر دارد و نیاز آن به نوشتن بسیار کم‌تر است. دلیلش را در ادامه خواهیم دید.</p>\n<p>برای ساخت یک نسخه ایستا که مدل داده را رندر کند و نمایش دهد، باید کامپوننت‌هایی بسازید که از بقیه کامپوننت‌ها استفاده می‌کنند و داده‌ها را از طریق <em>props</em> انتقال می‌دهند. <em>props</em> امکانی است که بوسیله آن، داده‌ها از کامپوننت والد (parent) به کامپوننت فرزند (child) منتقل می‌شوند.\nاگر که با مفهوم state آشنایی دارید، <strong>هرگز از آن برای ساخت نسخه ایستا استفاده نکنید!</strong> state برای ایجاد تعامل طراحی شده و داده‌ای است که در طول زمان تغییر می‌کند و از آن‌جایی که فعلا روی نسخه ایستا کار می‌کنیم، نیازی به آن نخواهیم داشت.</p>\n<p>می‌توانید روند ساخت را از بالا به پایین، یا از پایین به بالا شروع کنید. به این معنا که هم می‌توانید از بالاترین کامپوننت در سلسله مراتب قرار دارند (مثلا <code class=\"gatsby-code-text\">FilterableProductTable</code>) یا از کامپوننت‌هایی که در سطوح پایین‌تری قرار دارند (مثل <code class=\"gatsby-code-text\">ProductRow</code>) آغاز کنید. در مثال‌های ساده‌تر، معمولا شروع از بالا به پایین راحت‌تر است. در حالی‌که در پروژه‌های بزرگ‌تر، بهتر است که از پایین به بالا پیش بروید و همزمان با ساخت اپ، برای آن تست نیز بنویسید.</p>\n<p>در پایان این گام، شما کتابخانه‌ای از کامپوننت‌ها خواهید داشت که مدل داده را رندر می‌کند. از آنجایی که با نسخه ایستا سر و کار داریم، کامپوننت‌ها تنها متد <code class=\"gatsby-code-text\">render()</code> خواهند داشت.\nکامپوننتی که در راس سلسله مراتب قرار دارد (یعنی <code class=\"gatsby-code-text\">FilterableProductTable</code>) مدل داده‌ها را بعنوان یک prop دریافت می‌کند.\nاگر تغییراتی را در مدل داده‌های زیربنایی پروژه ایجاد کنید و دوباره <code class=\"gatsby-code-text\">ReactDOM.render()</code> را صدا بزنید، رابط کاربری به‌روز رسانی خواهد شد و می‌توانید ببینید که رابط کاربری چگونه و در کجا تغییر می‌کند.</p>\n<p><strong>جریان یکطرفه داده (one-way data flow)</strong> در ری‌اکت (که با نام <em>binding یک‌طرفه</em> نیز شناخته می‌شود) همه چیز را ماژولار و سریع نگه می‌دارد.</p>\n<p>اگر برای اجرای این بخش به کمک نیاز داشتید، به <a href=\"/docs/\">React docs</a> مراجعه کنید.</p>\n<h3 id=\"a-brief-interlude-props-vs-state\"><a href=\"#a-brief-interlude-props-vs-state\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>یک مکث مختصر: props در مقابل state </h3>\n<p>دو نوع داده “مدل” در ری‌اکت وجود دارد و خیلی مهم است که تفاوت این دو را بدانیم: اگر خیلی در این مورد مطمئن نیستید، نگاهی به  <a href=\"/docs/state-and-lifecycle.html\">مستندات رسمی ری‌اکت </a> بیندازید.</p>\n<p>علاوه بر این، می‌توانید به بخش <a href=\"/docs/faq-state.html#what-is-the-difference-between-state-and-props\">سوالات پرتکرار: تفاوت میان state و props چیست؟</a> مراجعه کنید.</p>\n<h2 id=\"step-3-identify-the-minimal-but-complete-representation-of-ui-state\"><a href=\"#step-3-identify-the-minimal-but-complete-representation-of-ui-state\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>قدم سوم: مشخص کردن یک نمونه حداقلی (اما کامل) از state های موردنیاز در رابط کاربری </h2>\n<p>برای تعاملی کردن رابط کاربری، باید بتوانید در مدل داده زیربنایی پروژه [همان داده‌های اولیه] تغییر ایجاد کنید. اینکار در ری‌اکت از طریق <strong>state</strong> انجام می‌شود.\nبرای ساخت اپ به صورت صحیح، ابتدا باید به مجموعه‌ای حداقلی از داده‌های قابل تغییر فکر کنید که در پروژه شما نیاز است. کلید این موضوع، <a href=\"https://en.wikipedia.org/wiki/Don%27t_repeat_yourself\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">اصل <em>خودت را تکرار نکن</em></a> است.\nتعیین کنید که در حال حاضر، مختصرترین مجموعه state که برنامه شما نیاز دارد چیست و بقیه موارد را به مرور، و در زمان لزوم محاسبه و تعیین کنید.</p>\n<p>برای مثال، اگر یک برنامه برای لیست کارها (TODO List) طراحی می‌کنید، یک آرایه از آیتم‌های موجود در لیست کارها را در دسترس نگه دارید. اما دیگر نیازی به تعیین یک state برای شمارش آیتم‌ها ندارید. به جای آن، زمان رندر کردن تعداد، می‌توانید از طول آرایه آیتم‌ها استفاده کنید.</p>\n<p>تمام تکه‌های داده را در مثال خودمان در نظر بگیرید:</p>\n<ul>\n<li>یک لیست اصلی از محصولات</li>\n<li>متنی که کاربر جستجو میکند</li>\n<li>مقدار checkbox</li>\n<li>لیست محصولات فیلتر شده پس از جستجو توسط کاربر</li>\n</ul>\n<p>به طور جداگانه سراغ هر یک از این موارد می‌رویم تا ببینیم که کدامشان state هستند. درمورد هر بخش، این ۳ سوال را از خودتان بپرسید:</p>\n<ol>\n<li>آیا این داده از طرف یک کامپوننت والد و بوسیله props انتقال داده شده؟ اگر جواب مثبت است، پس احتمالا این داده state نیست.</li>\n<li>آیا در طول زمان بدون تغییر می‌ماند؟ اگر اینطور است پس احتمالا باز هم state نیست.</li>\n<li>آیا می‌توانید آن را بر اساس یک state یا props موجود محاسبه کنید؟ اگر اینطور است، پس حتما این داده  state نیست.</li>\n</ol>\n<p>لیست اولیه و اصلی محصولات، بعنوان یک props منتقل می‌شود، بنابراین state نیست. اما به نظر میرسد که متن جستجو و مقدار چک باکس state هستند چرا که در طول زمان تغییر می‌کنند و نمی‌توان آن‌ها را به‌سیله داده دیگری محاسبه کرد. در نهایت، لیست محصولات فیلتر شده پس از جستجو هم state نیست، چرا که می‌توان آن را از ترکیب لیست اصلی و اولیه با متن سرچ کاربر و مقدار چک باکس بدست آورد.</p>\n<p>پس در مجموع، state این اپ عبارت است از:</p>\n<ul>\n<li>متنی که کاربر در فیلد جستجو وارد میکند</li>\n<li>مقدار checkbox</li>\n</ul>\n<h2 id=\"step-4-identify-where-your-state-should-live\"><a href=\"#step-4-identify-where-your-state-should-live\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>قدم چهارم: مشخص کنید که state در کجا باید قرار بگیرد </h2>\n<p data-height=\"600\" data-theme-id=\"0\" data-slug-hash=\"qPrNQZ\" data-default-tab=\"js\" data-user=\"lacker\" data-embed-version=\"2\" class=\"codepen\">این بخش را در <a href=\"https://codepen.io/gaearon/pen/qPrNQZ\">فکر کردن در چارچوب ری‌اکت: گام چهارم</a> روی <a href=\"https://codepen.io\">CodePen</a> ببینید.</p>\n<p>بعد از اینکه ما حداقل state مورد نیاز در پروژه را مشخص کردیم، نوبت این است که بدانیم هر state باید در کدام کامپوننت قرار بگیرد.</p>\n<p>به یاد داشته باشید: ری‌اکت بر مبنای جریان یک طرفه و رو به پایین داده در سلسله مراتب کامپوننت‌ها کار می‌کند. ممکن است این موضوع که کدام کامپوننت، کدام state را در خود جا می‌دهد، در اپتدا واضح نباشد.  <strong>اغلب این مساله، چالش برانگیزترین بخش برای افرادیست که تازه با ری‌اکت آشنا شده‌اند.</strong></p>\n<p>پس برای اینکه متوجه موضوع بشوید، این قدم‌ها را برای هر state در برنامه خود دنبال کنید:</p>\n<ul>\n<li>کامپوننت‌هایی را که چیزی را براساس آن state رندر می‌کنند، مشخص کنید.</li>\n<li>یک کامپوننت مشترک صاحب state را پیدا کنید (کامپوننتی که در سلسله مراتب برنامه، بالاتر از دیگر کامپوننت‌های استفاده کننده از state قرار می‌گیرد و خود نیز از آن state استفاده می‌کند)</li>\n<li>صاحب مشترک یا کامپوننت دیگری که در سلسله مراتب، بالاتر قرار می‌گیرد، باید صاحب state باشند.</li>\n<li>اگر نتوانستید کامپوننتی را پیدا کنید که قرار دادن state در آن منطقی باشد، یک کامپوننت جدید ایجاد کنید که منحصرا برای نگهداری state باشد و آن را جایی بالاتر از صاحب مشترک state در سلسله مراتب قرار دهید.</li>\n</ul>\n<p>حالا این استراتژی را برای برنامه خودمان اجرا کنیم:</p>\n<ul>\n<li>کامپوننت <code class=\"gatsby-code-text\">ProductTable</code> نیاز دارد که براساس state، لیست محصولات را فیلتر کند و کامپوننت <code class=\"gatsby-code-text\">SearchBar</code> هم نیاز دارد که متن جستجو و وضعیت checkbox را نمایش دهد.</li>\n<li>صاحب مشترک در این مثال، کامپوننت <code class=\"gatsby-code-text\">FilterableProductTable</code> است.</li>\n<li>پس منطقی به نظر میرسد که state ها را در کامپوننت <code class=\"gatsby-code-text\">FilterableProductTable</code> قرار دهیم.</li>\n</ul>\n<p>به این ترتیب، در ابتدا ویژگی <code class=\"gatsby-code-text\">this.state = {filterText: &#39;&#39;, inStockOnly: false}</code> را در بخش <code class=\"gatsby-code-text\">constructor</code>در کامپوننت <code class=\"gatsby-code-text\">FilterableProductTable</code> قرار می‌دهیم تا state ابتدایی برنامه شما را نشان دهد.</p>\n<p>سپس، <code class=\"gatsby-code-text\">filterText</code> و <code class=\"gatsby-code-text\">inStockOnly</code> را به کامپوننت‌های <code class=\"gatsby-code-text\">ProductTable</code> و <code class=\"gatsby-code-text\">SearchBar</code> بعنوان props انتقال می‌دهیم.\nدرنهایت، این props برای فیلتر وردی های محصولات در <code class=\"gatsby-code-text\">ProductTable</code> و مشخص کردن مقدار در checkbox موجود در <code class=\"gatsby-code-text\">SearchBar</code> به کار می‌روند.</p>\n<p>حالا می‌توانید ببینید که برنامه شما چطور عمل می‌کند: <code class=\"gatsby-code-text\">filterText</code> را به <code class=\"gatsby-code-text\">&quot;ball&quot;</code> تغییر بدهید و برنامه را دوباره بارگذاری کنید. خواهید دید که جدول داده‌ها به درستی تغییر می‌کند.</p>\n<h2 id=\"step-5-add-inverse-data-flow\"><a href=\"#step-5-add-inverse-data-flow\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>قدم پنجم: اضافه کردن جریان معکوس داده </h2>\n<p data-height=\"600\" data-theme-id=\"0\" data-slug-hash=\"LzWZvb\" data-default-tab=\"js,result\" data-user=\"rohan10\" data-embed-version=\"2\" data-pen-title=\"Thinking In React: Step 5\" class=\"codepen\">این بخش را در <a href=\"https://codepen.io/gaearon/pen/LzWZvb\">فکر کردن در چارچوب ری‌اکت: گام پنجم</a> در <a href=\"https://codepen.io\">CodePen</a> ببینید.</p>\n<p>تا به اینجای کار، ما برنامه‌ای ساختیم که به طور صحیح و به شکل تابعی از props و state، رندر می‌شد و جریان داده در آن از بالا به پایین بود.\nاما حالا زمان آن است که برنامه، جریان داده را به شکل معکوس و رو به بالا پشتیبانی کند: فرم‌های موجود در پایین‌ترین بخش سلسله مراتب کامپوننت‌ها، باید بتوانند state درون کامپوننت <code class=\"gatsby-code-text\">FilterableProductTable</code> را تغییر دهند.</p>\n<p>ری‌اکت، این جریان داده را شفاف می‌کند تا به کمک آن، بتوانید طرز کار برنامه‌تان را درک کنید، اما این مساله احتیاج به نوشتن و تایپ بیشتری نسبت به روش سنتی data binding دو طرفه دارد.</p>\n<p>در نسخه فعلی این مثال، اگه در فیلد جستجو تایپ کنید یا تیک checkbox  را بزنید، خواهید دید که ری‌اکت، ورودی شما را نادیده می‌گیرد. این موضوع عمدی است، چرا که ما تعیین کردیم، <code class=\"gatsby-code-text\">value</code> در <code class=\"gatsby-code-text\">input</code> همواره با مقدار  <code class=\"gatsby-code-text\">state</code> که از کامپوننت <code class=\"gatsby-code-text\">FilterableProductTable</code> منتقل می‌شود، برابر باشد.</p>\n<p>بیایید به این فکر کنیم که می‌خواهیم چه اتفاقی بیفتد؟ می‌خواهیم مطمئن شویم که هر زمان کاربر، تغییراتی را در فرم (فیلد جستجو یا checkbox) اعمال می‌کند، state به‌روز رسانی شده و تغییرات را منعکس کند.\nاز آنجایی که کامپوننت‌ها فقط مجاز به تغییر state موجود در خودشان هستند، کامپوننت <code class=\"gatsby-code-text\">FilterableProductTable</code> callbackهایی را به کامپوننت<code class=\"gatsby-code-text\">SearchBar</code> انتقال می‌دهد تا هر وقت نیاز به تغییر state وجود داشت، فراخوانی شوند.\nمی‌توانیم از رویداد <code class=\"gatsby-code-text\">onChange</code> برای ورودی‌ها استفاده کنیم تا به این طریق، کامپوننت <code class=\"gatsby-code-text\">FilterableProductTable</code> از لزوم اجرای تغییر مطلع شود.\nآن callback که از کامپوننت <code class=\"gatsby-code-text\">FilterableProductTable</code> انتقال می‌یابد،  <code class=\"gatsby-code-text\">setState()</code> است و باعث تغییر و به‌روز رسانی اپ میشود.</p>\n<h2 id=\"and-thats-it\"><a href=\"#and-thats-it\" aria-hidden class=\"anchor\"><svg aria-hidden=\"true\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>همین! </h2>\n<p>امیدواریم که این مطلب، به شما ایده داده باشد که چگونه باید درباره ساختن کامپوننت‌ها و برنامه‌ها در ری‌اکت فکر کنید. البته ممکن است که میزان نوشتن، بیشتر از حدی باشد که به آن عادت دارید، اما به یاد داشته باشید که کد، بیشتر از اینکه نوشته شود، خوانده می‌شود و خواندن این کد که به شکل ماژولار، ساده و شفاف نوشته شده است، بسیار راحت‌تر خواهد بود.</p>\n<p>به محض اینکه ساخت کتابخانه‌های بزرگ متشکل از کامپوننت‌ها را شروع کنید، بابت این شفافیت و ماژولار بودن سپاسگزار خواهید شد، و با وجود امکان استفاده مجدد از کدها، تعداد خط‌های کد شما به مرور کم‌تر خواهد شد!  :)</p>","frontmatter":{"title":"فکر کردن در چارچوب ری‌اکت","next":null,"prev":"composition-vs-inheritance.html"},"fields":{"path":"content/docs/thinking-in-react.md","slug":"docs/thinking-in-react.html"}}},"pageContext":{"slug":"docs/thinking-in-react.html"}},"staticQueryHashes":[]}