From cbf45200c914428128025ce7ca870ca2a5f4d5d2 Mon Sep 17 00:00:00 2001 From: Erfan <52595036+rfnmt@users.noreply.github.com> Date: Wed, 1 Jan 2020 13:38:05 +0330 Subject: [PATCH 1/5] Done! Translation process is completed --- content/docs/thinking-in-react.md | 50 ++++++++++++++++++------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/content/docs/thinking-in-react.md b/content/docs/thinking-in-react.md index 6e5e7ed94..c6b20b5b2 100644 --- a/content/docs/thinking-in-react.md +++ b/content/docs/thinking-in-react.md @@ -1,6 +1,6 @@ --- id: thinking-in-react -title: Thinking in React +title: فکر کردن در چارچوب ری‌اکت permalink: docs/thinking-in-react.html redirect_from: - 'blog/2013/11/05/thinking-in-react.html' @@ -8,17 +8,19 @@ redirect_from: prev: composition-vs-inheritance.html --- -React is, in our opinion, the premier way to build big, fast Web apps with JavaScript. It has scaled very well for us at Facebook and Instagram. +به عقیده ما، ری‌اکت بهترین راه برای ساخت وب اپلیکیشن هایی سریع و بزرگ، با استفاده از جاوااسکریپت است و برای ما در فیسبوک و اینستاگرام خیلی خوب جواب داده است. -One of the many great parts of React is how it makes you think about apps as you build them. In this document, we'll walk you through the thought process of building a searchable product data table using React. +ری‌اکت بخش های خیلی خوب زیادی دارد، اما یکی از بهترین آنها، چگونگی نگرش به اپ هایی است که مشغول به ساخت آنها هستید. +در این سند (Document)، به فرایند تفکر در ساخت یک جدول محصولات با قابلیت جستجو خواهیم پرداخت، و برای ساخت این جدول از ری‌اکت استفاده میکنیم. -## Start With A Mock {#start-with-a-mock} -Imagine that we already have a JSON API and a mock from our designer. The mock looks like this: +## شروع با یک مدل {#start-with-a-mock} + +تصور کنید که ما از قبل یک JSON API و یک مدل، که توسط طراح آماده شده، داریم. مدل آماده شده، چیزی شبیه به این است: ![Mockup](../images/blog/thinking-in-react-mock.png) -Our JSON API returns some data that looks like this: +و JSON API هم این اطلاعات را در خود جا داده است: ``` [ @@ -31,27 +33,35 @@ Our JSON API returns some data that looks like this: ]; ``` -## Step 1: Break The UI Into A Component Hierarchy {#step-1-break-the-ui-into-a-component-hierarchy} +## قدم اول: رابط کاربری را به یک سلسله از کامپوننت ها تقسیم کنید{#step-1-break-the-ui-into-a-component-hierarchy} + +اولین کاری که باید کنید، این است که دور هر کدام از کامپوننت های موجود خط بکشید و تمامی کامپوننت ها را به همراه زیرمجموعه های آن مشخص کنید و برای هر کدام یک نام در نظر بگیرید. (هر کامپوننت ممکن است یک یا چند کامپوننت زیر مجموعه داشته باشد) -The first thing you'll want to do is to draw boxes around every component (and subcomponent) in the mock and give them all names. If you're working with a designer, they may have already done this, so go talk to them! Their Photoshop layer names may end up being the names of your React components! +اگر به همراه یک طراح (دیزاینر) کار میکنید، ممکن است او قبلا همین کار را انجام داده باشد. نامگذاری آنها برای لایه های مختلف در فایل فتوشاپی که تهیه کرده اند، میتواند نام کامپوننت ها در کد شما هم باشد! -But how do you know what should be its own component? Use the same techniques for deciding if you should create a new function or object. One such technique is the [single responsibility principle](https://en.wikipedia.org/wiki/Single_responsibility_principle), that is, a component should ideally only do one thing. If it ends up growing, it should be decomposed into smaller subcomponents. +اما چطور بفهمیم که یک بخش باید تبدیل به یک کامپوننت جداگانه شود؟ در این موارد بهتر است از همان تکنیک هایی استفاده کنیم که زمان تصمیم گیری برای تعریف یک تابع Function یا یک شیء Object جدید به کمک مان می آمدند. +یکی از این تکنیک ها ["اصل مسئولیت واحد" یا "اصل تک وظیفگی" ](https://en.wikipedia.org/wiki/Single_responsibility_principle), است. +این اصل بیان میکند که هر کامپوننت، باید در حالت ایده آل فقط یک کار را انجام دهد و اگر وظایف آن گسترش یافت، باید برای برای آن کامپوننت های زیر مجموعه Subcomponent تعریف کرد و وظایف اضافی را به آنها سپرد. -Since you're often displaying a JSON data model to a user, you'll find that if your model was built correctly, your UI (and therefore your component structure) will map nicely. That's because UI and data models tend to adhere to the same *information architecture*. Separate your UI into components, where each component matches one piece of your data model. +از آنجایی که اغلب یک مدل داده جیسون (JSON Data Model) به کاربر نشان داده میشود، متوجه خواهید شد که اگر این مدل درست ساخته شده باشد، رابط کاربری و ساختار کامپوننت های شما هم به درستی قابل ترسیم و تعیین خواهد بود. +این بدان دلیل است که مدل داده (Data Model) و رابط کاربری معمولا از یک معماری اطلاعات (information architecture) یکسان تبعیت میکنند. +رابط کاربری را طوری به کامپوننت های مختلف تقسیم کنید که هر کامپوننت با بخش خاصی از مدل داده مرتبط باشد. ![Component diagram](../images/blog/thinking-in-react-components.png) -You'll see here that we have five components in our app. We've italicized the data each component represents. +در این تصویر می بینید که ما پنج کامپوننت در برنامه خود داریم و اطلاعاتی که هر کامپوننت نمایش میدهد را با حروف ایتالیک مشخص کرده ایم: - 1. **`FilterableProductTable` (orange):** contains the entirety of the example - 2. **`SearchBar` (blue):** receives all *user input* - 3. **`ProductTable` (green):** displays and filters the *data collection* based on *user input* - 4. **`ProductCategoryRow` (turquoise):** displays a heading for each *category* - 5. **`ProductRow` (red):** displays a row for each *product* + 1. **`FilterableProductTable` (نارنجی):** شامل تمام برنامه + 2. **`SearchBar` (آبی):** *ورودی های کاربر* را دریافت میکند + 3. **`ProductTable` (سبز):** تمامی *مجموعه اطلاعات* را با توجه به *ورودی کاربر* نمایش داده و اطلاعات را فیلتر میکند + 4. **`ProductCategoryRow` (فیروزه ای):** یک تیتر را برای هر *دسته* نمایش میدهد + 5. **`ProductRow` (قرمز):** یک ردیف را برای هر *محصول* نمایش میدهد -If you look at `ProductTable`, you'll see that the table header (containing the "Name" and "Price" labels) isn't its own component. This is a matter of preference, and there's an argument to be made either way. For this example, we left it as part of `ProductTable` because it is part of rendering the *data collection* which is `ProductTable`'s responsibility. However, if this header grows to be complex (e.g., if we were to add affordances for sorting), it would certainly make sense to make this its own `ProductTableHeader` component. +اگر نگاهی به کامپوننت `ProductTable`بیندازید، متوجه میشوید که تیترهای جدول (شامل "Name" و “Price”) کامپوننت جداگانه ای ندارند که بیشتر یک موضوع سلیقه ای است و دلایل و استدلال هایی برای استفاده یا عدم استفاده از یک کامپوننت جداگانه برای آنها وجود دارد. +در این مثال، آن را بخشی از `ProductTable` قرار دادیم، چرا که جزئی از *مجموعه داده ها data collection* بوده و رندر کردن آن وظیفه `ProductTable` است. +با این حال، اگر هدر جدول پیچیده تر شود (مثلا اگر گزینه ای برای مرتب کردن لیست محصولات اضافه میکردیم)، مطمئنا منطقی تر بود که آنها در یک کامپوننت جداگانه با نام `ProductTableHeader` بگذاریم -Now that we've identified the components in our mock, let's arrange them into a hierarchy. Components that appear within another component in the mock should appear as a child in the hierarchy: +حالا که کامپوننت های موجود در پروژه را مشخص کردیم، وقتش رسیده که سلسله مراتب آنها را نیز تعیین کنیم. کامپوننت هایی که با توجه به مدل، درون یک کامپوننت دیگر قرار میگیرند، فرزند آن محسوب میشوند: * `FilterableProductTable` * `SearchBar` @@ -59,9 +69,9 @@ Now that we've identified the components in our mock, let's arrange them into a * `ProductCategoryRow` * `ProductRow` -## Step 2: Build A Static Version in React {#step-2-build-a-static-version-in-react} +## قدم دوم: یک نسخه ایستا (Static) در ری‌اکت بسازید {#step-2-build-a-static-version-in-react} -

See the Pen Thinking In React: Step 2 on CodePen.

+

این بخش را در فکر کردن در چارچوب ری‌اکت: گام دوم روی CodePenببینید.

Now that you have your component hierarchy, it's time to implement your app. The easiest way is to build a version that takes your data model and renders the UI but has no interactivity. It's best to decouple these processes because building a static version requires a lot of typing and no thinking, and adding interactivity requires a lot of thinking and not a lot of typing. We'll see why. From 67432522b2f9fd6e469b9e8d003c632bc8c3d6cd Mon Sep 17 00:00:00 2001 From: Erfan <52595036+rfnmt@users.noreply.github.com> Date: Wed, 1 Jan 2020 13:41:59 +0330 Subject: [PATCH 2/5] 02 --- content/docs/thinking-in-react.md | 114 ++++++++++++++++++------------ 1 file changed, 67 insertions(+), 47 deletions(-) diff --git a/content/docs/thinking-in-react.md b/content/docs/thinking-in-react.md index c6b20b5b2..7976ee3d2 100644 --- a/content/docs/thinking-in-react.md +++ b/content/docs/thinking-in-react.md @@ -58,6 +58,7 @@ prev: composition-vs-inheritance.html 5. **`ProductRow` (قرمز):** یک ردیف را برای هر *محصول* نمایش میدهد اگر نگاهی به کامپوننت `ProductTable`بیندازید، متوجه میشوید که تیترهای جدول (شامل "Name" و “Price”) کامپوننت جداگانه ای ندارند که بیشتر یک موضوع سلیقه ای است و دلایل و استدلال هایی برای استفاده یا عدم استفاده از یک کامپوننت جداگانه برای آنها وجود دارد. + در این مثال، آن را بخشی از `ProductTable` قرار دادیم، چرا که جزئی از *مجموعه داده ها data collection* بوده و رندر کردن آن وظیفه `ProductTable` است. با این حال، اگر هدر جدول پیچیده تر شود (مثلا اگر گزینه ای برای مرتب کردن لیست محصولات اضافه میکردیم)، مطمئنا منطقی تر بود که آنها در یک کامپوننت جداگانه با نام `ProductTableHeader` بگذاریم @@ -71,86 +72,105 @@ prev: composition-vs-inheritance.html ## قدم دوم: یک نسخه ایستا (Static) در ری‌اکت بسازید {#step-2-build-a-static-version-in-react} -

این بخش را در فکر کردن در چارچوب ری‌اکت: گام دوم روی CodePenببینید.

+

این بخش را در فکر کردن در چارچوب ری‌اکت: گام دوم روی CodePen ببینید.

-Now that you have your component hierarchy, it's time to implement your app. The easiest way is to build a version that takes your data model and renders the UI but has no interactivity. It's best to decouple these processes because building a static version requires a lot of typing and no thinking, and adding interactivity requires a lot of thinking and not a lot of typing. We'll see why. +بعد از اینکه سلسله مراتب را مشخص کردید، نوبت به پیاده سازی اپ میرسد. راحتترین راه این است که نسخه ای بسازید که مدل داده ها را میگیرد و رابط کاربری را تولید میکند اما هیچ تعاملی با کاربر ندارد. +بهتر است که این دو فرایند (نوشتن نسخه تعاملی و ایستا Static) را از هم جدا کنیم، به این دلیل که ساخت نسخه ایستا، به مقدار زیادی نوشتن و مقدار کمی فکر کردن نیاز دارد. اما اضافه کردن امکان تعامل و پویایی، احتیاج به مقدار زیادی تفکر دارد و نیاز آن به نوشتن بسیار کمتر است. دلیلش را در ادامه خواهیم دید. + + +برای ساخت یک نسخه ایستا که مدل داده را رندر کند و نمایش دهد، باید کامپوننت هایی بسازید که از بقیه کامپوننت ها استفاده میکنند و داده ها را از طریق *props* انتقال میدهند. *Props* امکانی است که بوسیله آن، داده ها از کامپوننت والد parent به کامپوننت فرزند child منتقل میشوند. +اگر که با مفهوم state آشنایی دارید، **هرگز از آن برای ساخت نسخه ایستا استفاده نکنید!** State برای ایجاد تعامل طراحی شده و داده ای است که در طول زمان تغییر میکند و از آنجایی که فعلا روی نسخه ایستا کار میکنیم، نیازی به آن نخواهیم داشت. + +میتوانید روند ساخت را از بالا به پایین یا از پایین به بالا شروع کنید. به این معنا که هم میتوانید از بالاترین کامپوننت در سلسله مراتب آغاز کنید (مثلا `FilterableProductTable`) یا از کامپوننت هایی که در سطوح پایین تری قرار دارند (مثل `ProductRow`). در مثال ها ساده تر، معمولا شروع از بالا به پایین راحت تر است. در حالیکه در پروژه های بزرگتر، بهتر است که از پایین به بالا پیش بروید و همزمان با ساخت اپ، برای آن تست نیز بنویسید. + +در پایان این گام، شما کتابخانه ای از کامپوننت ها خواهید داشت که مدل داده data model را رندر میکند. از آنجایی که با نسخه ایستا سر و کار داریم، کامپوننت ها تنها متد `render()` خواهند داشت. +کامپوننتی که در راس سلسله مراتب قرار دارد (یعنی `FilterableProductTable`) مدل داده ها را بعنوان یک prop دریافت میکند. +اگر تغییراتی را در مدل داده های زیربنایی پروژه ایجاد کنید و دوباره `ReactDOM.render()` را صدا بزنید، رابط کاربری به روز رسانی update خواهد شد و میتوانید ببینید که رابط کاربری چگونه و در کجا تغییر میکند. +**جریان یکطرفه داده one-way data flow** در ری‌اکت (که با نام *الزام و محدودیت یک طرفه one-way binding* نیز شناخته میشود) همه چیز را ماژولار و سریع نگه میدارد. -To build a static version of your app that renders your data model, you'll want to build components that reuse other components and pass data using *props*. *props* are a way of passing data from parent to child. If you're familiar with the concept of *state*, **don't use state at all** to build this static version. State is reserved only for interactivity, that is, data that changes over time. Since this is a static version of the app, you don't need it. +اگر برای اجرای این بخش به کمک نیاز داشتید، به [React docs](/docs/) مراجعه کنید. -You can build top-down or bottom-up. That is, you can either start with building the components higher up in the hierarchy (i.e. starting with `FilterableProductTable`) or with the ones lower in it (`ProductRow`). In simpler examples, it's usually easier to go top-down, and on larger projects, it's easier to go bottom-up and write tests as you build. +### یک مکث مختصر: props در مقابل state {#a-brief-interlude-props-vs-state} -At the end of this step, you'll have a library of reusable components that render your data model. The components will only have `render()` methods since this is a static version of your app. The component at the top of the hierarchy (`FilterableProductTable`) will take your data model as a prop. If you make a change to your underlying data model and call `ReactDOM.render()` again, the UI will be updated. You can see how your UI is updated and where to make changes. React's **one-way data flow** (also called *one-way binding*) keeps everything modular and fast. +دو نوع داده "نمونه" (model) در ری¬اکت وجود دارد و خیلی مهم است که تفاوت این دو را بدانیم: اگر خیلی در این مورد مطمئن نیستید، نگاهی به [مستندات رسمی ری‌اکت ](/docs/state-and-lifecycle.html) بیندازید. +علاوه براین، میتوانید به بخش [سوالات پرتکرار: تفاوت میان state و props چیست؟](/docs/faq-state.html#what-is-the-difference-between-state-and-props) مراجعه کنید. -Refer to the [React docs](/docs/) if you need help executing this step. +## قدم سوم: مشخص کردن یک نمونه حداقلی اما کامل از state های موردنیاز در رابط کاربری {#step-3-identify-the-minimal-but-complete-representation-of-ui-state} -### A Brief Interlude: Props vs State {#a-brief-interlude-props-vs-state} +برای تعاملی کردن رابط کاربری، باید بتوانید در مدل داده زیربنایی پروژه (همان داده¬های اولیه) تغییر ایجاد کنید. اینکار در ری¬اکت از طریق **state** انجام میشود. -There are two types of "model" data in React: props and state. It's important to understand the distinction between the two; skim [the official React docs](/docs/state-and-lifecycle.html) if you aren't sure what the difference is. See also [FAQ: What is the difference between state and props?](/docs/faq-state.html#what-is-the-difference-between-state-and-props) +برای ساخت اپ به صورت صحیح، ابتدا باید به مجموعه ای حداقلی از داده های قابل تغییر فکر کنید که در پروژه شما نیاز است. کلید این موضوع، [اصل *خودت را تکرار نکن*](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) است. +تعیین کنید که در حال حاضر، مختصرترین مجموعه state که برنامه شما نیاز دارد چیست و بقیه موارد را به مرور، و در زمان لزوم محاسبه و تعیین کنید. -## Step 3: Identify The Minimal (but complete) Representation Of UI State {#step-3-identify-the-minimal-but-complete-representation-of-ui-state} +برای مثال، اگر یک برنامه برای لیست کارها TODO List طراحی میکنید، یک آرایه array از آیتم های موجود در لیست کارها را در دسترس نگه دارید. اما دیگر نیازی به تعیین یک state برای شمارش آیتم ها ندارید. به جای آن، زمان رندر کردن تعداد، میتوانید از طول آرایه آیتم ها (Array.length) استفاده کنید. -To make your UI interactive, you need to be able to trigger changes to your underlying data model. React achieves this with **state**. +تمام بخش های داده در مثال خودمان را در نظر بگیرید: -To build your app correctly, you first need to think of the minimal set of mutable state that your app needs. The key here is [DRY: *Don't Repeat Yourself*](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself). Figure out the absolute minimal representation of the state your application needs and compute everything else you need on-demand. For example, if you're building a TODO list, keep an array of the TODO items around; don't keep a separate state variable for the count. Instead, when you want to render the TODO count, take the length of the TODO items array. + * یک لیست اصلی از محصولات + * متنی که کاربر جستجو میکند + * مقدار (value) چک باکس + * لیست محصولات فیلتر شده پس از جستجو توسط کاربر -Think of all of the pieces of data in our example application. We have: +به طور جداگانه سراغ هر یک از این موارد میرویم تا ببینیم که کدامشان state هستند. درمورد هر بخش، این 3 سوال را از خودتان بپرسید: - * The original list of products - * The search text the user has entered - * The value of the checkbox - * The filtered list of products + 1. آیا این داده از طرف یک کامپوننت والد و بوسیله props انتقال داده شده؟ اگر جواب مثبت است، پس احتمالا این داده state نیست. + 2. آیا در طول زمان بدون تغییر می ماند؟ اگر اینطور است پس احتمالا باز هم state نیست. + 3. آیا میتوانید آن را بر اساس یک state یا props موجود محاسبه کنید؟ (مثل همان طول لیست کارها!) اگر اینطور است، پس حتما این داده state نیست. -Let's go through each one and figure out which one is state. Ask three questions about each piece of data: +لیست اولیه و اصلی محصولات، بعنوان یک props منتقل میشود، بنابراین state نیست. اما به نظر میرسد که متن جستجو و مقدار چک باکس state هستند چرا که در طول زمان تغییر میکنند و نمیتوان آن ها را بوسیله داده دیگری محاسبه کرد. در نهایت، لیست محصولات فیلتر شده پس از جستجو هم state نیست، چرا که میتوان آن را از ترکیب لیست اصلی و اولیه با متن سرچ کاربر و مقدار چک باکس بدست آورد. - 1. Is it passed in from a parent via props? If so, it probably isn't state. - 2. Does it remain unchanged over time? If so, it probably isn't state. - 3. Can you compute it based on any other state or props in your component? If so, it isn't state. +پس در مجموع، state این اپ عبارتند از: -The original list of products is passed in as props, so that's not state. The search text and the checkbox seem to be state since they change over time and can't be computed from anything. And finally, the filtered list of products isn't state because it can be computed by combining the original list of products with the search text and value of the checkbox. + * متنی که کاربر در فیلد جستجو وارد میکند + * مقدار (value) چک باکس -So finally, our state is: +## قدم چهارم: مشخص کنید که state در کجا باید قرار بگیرد {#step-4-identify-where-your-state-should-live} - * The search text the user has entered - * The value of the checkbox +

این بخش را در فکر کردن در چارچوب ری‌اکت: گام چهارم روی CodePen ببینید.

-## Step 4: Identify Where Your State Should Live {#step-4-identify-where-your-state-should-live} +بعد از اینکه ما حداقل state مورد نیاز در پروژه را مشخص کردیم، نوبت این است که بدانیم هر state باید در کدام کامپوننت قرار بگیرد. -

See the Pen Thinking In React: Step 4 on CodePen.

+به یاد داشته باشید: ری¬اکت بر مبنای جریان یک طرفه و رو به پایین داده در سلسله مراتب کامپوننت ها کار میکند. ممکن است این موضوع که کدام کامپوننت، کدام state را در خود جا میدهد، فورا مشخص و واضح نباشد. **اغلب این مساله، چالش برانگیزترین بخش برای افرادیست که تازه با ری‌اکت آشنا شده اند.** -OK, so we've identified what the minimal set of app state is. Next, we need to identify which component mutates, or *owns*, this state. +پس برای اینکه متوجه موضوع بشوید، این قدم ها را برای هر state در برنامه خود دنبال کنید: -Remember: React is all about one-way data flow down the component hierarchy. It may not be immediately clear which component should own what state. **This is often the most challenging part for newcomers to understand,** so follow these steps to figure it out: + * کامپوننت هایی را که چیزی را براساس آن state رندر میکنند، مشخص کنید. + * یک کامپوننت مشترک صاحب state را پیدا کنید (کامپوننتی که در سلسله مراتب برنامه، بالاتر از دیگر کامپوننت های استفاده کننده از state قرار میگیرد و خود نیز از آن state استفاده میکند) + * صاحب مشترک یا کامپوننت دیگری که در سلسله مراتب، بالاتر قرار میگیرد، باید صاحب state باشند. + * اگر نتوانستید کامپوننتی را پیدا کنید که قرار دادن state در آن منطقی باشد، یک کامپوننت جدید ایجاد کنید که منحصرا برای نگهداری state باشد و آن را جایی بالاتر از صاحب مشترک state (در سلسله مراتب کامپوننت ها) قرار دهید. -For each piece of state in your application: +حالا این استراتژی را برای برنامه خودمان اجرا کنیم: - * Identify every component that renders something based on that state. - * Find a common owner component (a single component above all the components that need the state in the hierarchy). - * Either the common owner or another component higher up in the hierarchy should own the state. - * If you can't find a component where it makes sense to own the state, create a new component solely for holding the state and add it somewhere in the hierarchy above the common owner component. + * کامپوننت `ProductTable` نیاز دارد که براساس state، لیست محصولات را فیلتر کند و کامپوننت `SearchBar` هم نیاز دارد که متن جستجو و مقدار چک باکس را نمایش دهد (دو state موجود در برنامه) + * صاحب مشترک در این مثال، کامپوننت `FilterableProductTable` است. + * پس منطقی به نظر میرسد که state ها را در کامپوننت `FilterableProductTable` قرار دهیم. -Let's run through this strategy for our application: +به این ترتیب، در ابتدا ویژگی `this.state = {filterText: '', inStockOnly: false}` را در بخش `constructor`در کامپوننت `FilterableProductTable` قرار میدهیم تا state ابتدایی برنامه شما را نشان دهد. - * `ProductTable` needs to filter the product list based on state and `SearchBar` needs to display the search text and checked state. - * The common owner component is `FilterableProductTable`. - * It conceptually makes sense for the filter text and checked value to live in `FilterableProductTable` +سپس، `filterText` و `inStockOnly` را به کامپوننت های `ProductTable` و `SearchBar` بعنوان props انتقال میدهیم. +درنهایت، این props برای فیلتر ردیف های محصولات در `ProductTable` و مشخص کردن مقدار در چک باکس موجود در `SearchBar` به کار میروند. -Cool, so we've decided that our state lives in `FilterableProductTable`. First, add an instance property `this.state = {filterText: '', inStockOnly: false}` to `FilterableProductTable`'s `constructor` to reflect the initial state of your application. Then, pass `filterText` and `inStockOnly` to `ProductTable` and `SearchBar` as a prop. Finally, use these props to filter the rows in `ProductTable` and set the values of the form fields in `SearchBar`. +حالا میتوانید ببینید که برنامه شما چطور عمل میکند: `filterText` را به `"ball"` تغییر بدید و برنامه را دوباره بارگذاری (refresh) کنید. خواهید دید که جدول داده ها به درستی تغییر میکند. -You can start seeing how your application will behave: set `filterText` to `"ball"` and refresh your app. You'll see that the data table is updated correctly. +## قدم پنجم: اضافه کردن جریان معکوس داده {#step-5-add-inverse-data-flow} -## Step 5: Add Inverse Data Flow {#step-5-add-inverse-data-flow} +

این بخش را در فکر کردن در چارچوب ری‌اکت: گام پنجم در CodePen ببینید.

-

See the Pen Thinking In React: Step 5 on CodePen.

+تا به اینجای کار، ما برنامه ای ساختیم که به طور صحیح و به شکل تابعی از props و state، رندر میشد و جریان داده در آن از بالا به پایین بود. +اما حالا زمان آن است که برنامه، جریان داده را به شکل معکوس و رو به بالا پشتیبانی کند: فرم های موجود در پایین ترین بخش سلسله مراتب کامپوننت ها، باید بتوانند state درون کامپوننت `FilterableProductTable` را تغییر دهند. -So far, we've built an app that renders correctly as a function of props and state flowing down the hierarchy. Now it's time to support data flowing the other way: the form components deep in the hierarchy need to update the state in `FilterableProductTable`. +ری‌اکت، این جریان داده را ساده و شفاف میکند تا به کمک آن، بتوانید طرز کار برنامه تان را درک کنید، اما این مساله احتیاج به نوشتن و تایپ بیشتری نسبت به data binding دو طرفه و مرسوم دارد. -React makes this data flow explicit to help you understand how your program works, but it does require a little more typing than traditional two-way data binding. +اگه در فیلد جستجو تایپ کنید یا مقدار چک باکس را تغییر دهید (تیک آن را فعال کنید) خواهید که ری‌اکت، این تغییرات را نادیده میگیرد. این موضوع عمدی است، چرا که ما تعیین کردیم، `value` در `input` همواره با مقدار `state` که از کامپوننت `FilterableProductTable` منتقل میشود، برابر باشد. -If you try to type or check the box in the current version of the example, you'll see that React ignores your input. This is intentional, as we've set the `value` prop of the `input` to always be equal to the `state` passed in from `FilterableProductTable`. +بیایید به این فکر کنیم که میخواهیم چه اتفاقی بیفتد؟ میخواهیم مطمئن شویم که هر زمان کاربر، تغییراتی را در فرم (فیلد جستجو یا چک باکس) اعمال میکند، state به روز رسانی شده و تغییرات را منعکس کند. +از آنجایی که کامپوننت ها فقط مجاز به تغییر state موجود در خودشان هستند، کامپوننت `FilterableProductTable` کال بک هایی (callback) را به کامپوننت`SearchBar` انتقال میدهد تا هر وقت نیاز به تغییر state وجود داشت، اجرا شوند. +میتوانیم از رویداد `onChange` برای ورودی ها استفاده کنیم تا به این طریق، کامپوننت `FilterableProductTable` از لزوم اجرای تغییر مطلع شود. +آن کال بک که از کامپوننت `FilterableProductTable` انتقال می یابد، `setState()` است و باعث تغییر و به روز رسانی (update) اپ میشود. -Let's think about what we want to happen. We want to make sure that whenever the user changes the form, we update the state to reflect the user input. Since components should only update their own state, `FilterableProductTable` will pass callbacks to `SearchBar` that will fire whenever the state should be updated. We can use the `onChange` event on the inputs to be notified of it. The callbacks passed by `FilterableProductTable` will call `setState()`, and the app will be updated. +## همین! {#and-thats-it} -## And That's It {#and-thats-it} +امیدواریم که این مطلب، به شما ایده داده باشد که چگونه باید درباره ساختن کامپوننت ها و برنامه ها در ری¬اکت فکر کنید. البته ممکن است که میزان نوشتن، بیشتر از حدی باشد که به آن عادت دارید، اما به یاد داشته باشید که کد، بیشتر از اینکه نوشته شود، خوانده میشود و خواندن این کد که شکل ماژولار، ساده و شفاف نوشته شده است، بسیار راحت تر خواهد بود. -Hopefully, this gives you an idea of how to think about building components and applications with React. While it may be a little more typing than you're used to, remember that code is read far more than it's written, and it's less difficult to read this modular, explicit code. As you start to build large libraries of components, you'll appreciate this explicitness and modularity, and with code reuse, your lines of code will start to shrink. :) +به محض اینکه ساخت کتابخانه های بزرگ متشکل از کامپوننت ها را شروع کنید، بابت این شفافیت و ماژولار بودن سپاسگزار خواهید شد، و با وجود امکان استفاده مجدد از کدها، تعداد خطوط کد شما، شروع به آب رفتن میکند و کوچکتر و کوتاه تر خواهند شد! :) \ No newline at end of file From a0aa1920b2b788979a7f14c483ad2970b3fa3095 Mon Sep 17 00:00:00 2001 From: Erfan <52595036+rfnmt@users.noreply.github.com> Date: Wed, 1 Jan 2020 13:50:05 +0330 Subject: [PATCH 3/5] Translation process is completed --- content/docs/hooks-intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/hooks-intro.md b/content/docs/hooks-intro.md index 7c0d85210..f04be9fd6 100644 --- a/content/docs/hooks-intro.md +++ b/content/docs/hooks-intro.md @@ -54,7 +54,7 @@ function Example() { **اگر هم‌‌اکنون می‌‌خواهید یادگیری هوک‌‌ها را شروع کنید، [مستقیم به صفحه‌‌ی بعد بروید!](/docs/hooks-overview.html)** البته می‌‌توانید مطالعه‌‌ این صفحه را ادامه دهید و با دلایلی که هوک‌‌ها را به ری‌‌اکت اضافه کردیم و اینکه چگونه بدون بازنویسی اپلیکیشن‌‌های قبلی از آن‌‌ها استفاده خواهیم کرد، آشنا شوید. -## انگیزه +## انگیزه {#انگیزه} هوک‌ها مشکلات مختلفی که ظاهرا به هم ارتباط ندارند را حل می‌کنند. مواردی که ما طی در نوشتن و نگهداری هزاران کامپوننت طی پنج سال با آن مواجه شده‌ایم. اگر درحال یادگیری ری‌اکت هستید، هروز از آن استفاده می‌کنید یا از کتابخانه مشابهی استفاده می‌کنید که بر پایه کامپوننت طراحی شده‌است، احتمالا به این مشکلات بر خورد کرده‌اید. From 3fc7fc986ae55bba91c13075244be980eb82fa14 Mon Sep 17 00:00:00 2001 From: Erfan <52595036+rfnmt@users.noreply.github.com> Date: Sun, 19 Jan 2020 16:15:25 +0330 Subject: [PATCH 4/5] Improvement according to reviews --- content/docs/thinking-in-react.md | 106 +++++++++++++++--------------- 1 file changed, 52 insertions(+), 54 deletions(-) diff --git a/content/docs/thinking-in-react.md b/content/docs/thinking-in-react.md index 7976ee3d2..071216c78 100644 --- a/content/docs/thinking-in-react.md +++ b/content/docs/thinking-in-react.md @@ -10,7 +10,7 @@ prev: composition-vs-inheritance.html به عقیده ما، ری‌اکت بهترین راه برای ساخت وب اپلیکیشن هایی سریع و بزرگ، با استفاده از جاوااسکریپت است و برای ما در فیسبوک و اینستاگرام خیلی خوب جواب داده است. -ری‌اکت بخش های خیلی خوب زیادی دارد، اما یکی از بهترین آنها، چگونگی نگرش به اپ هایی است که مشغول به ساخت آنها هستید. +ری‌اکت بخش‌های خیلی خوب زیادی دارد، اما یکی از بهترین آنها، چگونگی نگرش به اپ‌هایی است که مشغول به ساخت آنها هستید. در این سند (Document)، به فرایند تفکر در ساخت یک جدول محصولات با قابلیت جستجو خواهیم پرداخت، و برای ساخت این جدول از ری‌اکت استفاده میکنیم. @@ -20,7 +20,7 @@ prev: composition-vs-inheritance.html ![Mockup](../images/blog/thinking-in-react-mock.png) -و JSON API هم این اطلاعات را در خود جا داده است: +و JSON API هم داده‌هایی را باز می‌گرداند که به صورت زیر است: ``` [ @@ -33,36 +33,35 @@ prev: composition-vs-inheritance.html ]; ``` -## قدم اول: رابط کاربری را به یک سلسله از کامپوننت ها تقسیم کنید{#step-1-break-the-ui-into-a-component-hierarchy} +## قدم اول: رابط کاربری را به یک سلسله از کامپوننت‌ها تقسیم کنید{#step-1-break-the-ui-into-a-component-hierarchy} -اولین کاری که باید کنید، این است که دور هر کدام از کامپوننت های موجود خط بکشید و تمامی کامپوننت ها را به همراه زیرمجموعه های آن مشخص کنید و برای هر کدام یک نام در نظر بگیرید. (هر کامپوننت ممکن است یک یا چند کامپوننت زیر مجموعه داشته باشد) +اولین کاری که باید کنید، این است که دور هر کدام از کامپوننت‌های موجود خط بکشید و تمامی کامپوننت‌ها را به همراه زیرمجموعه‌های آن (Subcomponents) مشخص کنید و برای هر کدام یک نام در نظر بگیرید. (هر کامپوننت ممکن است یک یا چند کامپوننت زیرمجموعه داشته باشد) -اگر به همراه یک طراح (دیزاینر) کار میکنید، ممکن است او قبلا همین کار را انجام داده باشد. نامگذاری آنها برای لایه های مختلف در فایل فتوشاپی که تهیه کرده اند، میتواند نام کامپوننت ها در کد شما هم باشد! +اگر به همراه یک طراح (دیزاینر) کار میکنید، ممکن است او قبلا همین کار را انجام داده باشد. نامگذاری آنها برای لایه‌های مختلف در فایل فتوشاپی که تهیه کرده‌اند، میتواند نام کامپوننت‌ها در کد شما هم باشد! -اما چطور بفهمیم که یک بخش باید تبدیل به یک کامپوننت جداگانه شود؟ در این موارد بهتر است از همان تکنیک هایی استفاده کنیم که زمان تصمیم گیری برای تعریف یک تابع Function یا یک شیء Object جدید به کمک مان می آمدند. -یکی از این تکنیک ها ["اصل مسئولیت واحد" یا "اصل تک وظیفگی" ](https://en.wikipedia.org/wiki/Single_responsibility_principle), است. -این اصل بیان میکند که هر کامپوننت، باید در حالت ایده آل فقط یک کار را انجام دهد و اگر وظایف آن گسترش یافت، باید برای برای آن کامپوننت های زیر مجموعه Subcomponent تعریف کرد و وظایف اضافی را به آنها سپرد. +اما چطور بفهمیم که یک بخش باید تبدیل به یک کامپوننت جداگانه شود؟ در این موارد بهتر است از همان تکنیک‌هایی استفاده کنیم که زمان تصمیم‌گیری برای تعریف یک تابع Function یا یک شیء Object جدید به کمک‌‌‌مان می آمدند. +یکی از این تکنیک‌ها ["اصل مسئولیت واحد" "(single responsibility principle)" ](https://en.wikipedia.org/wiki/Single_responsibility_principle) است. +این اصل بیان میکند که هر کامپوننت، باید در حالت ایده‌آل فقط یک کار را انجام دهد و اگر وظایف آن گسترش یافت، باید برای آن کامپوننت‌های زیرمجموعه تعریف کرد و وظایف اضافی را به آنها سپرد. -از آنجایی که اغلب یک مدل داده جیسون (JSON Data Model) به کاربر نشان داده میشود، متوجه خواهید شد که اگر این مدل درست ساخته شده باشد، رابط کاربری و ساختار کامپوننت های شما هم به درستی قابل ترسیم و تعیین خواهد بود. +از آنجایی که اغلب یک مدل داده JSON به کاربر نشان داده میشود، متوجه خواهید شد که اگر این مدل درست ساخته شده باشد، رابط کاربری و ساختار کامپوننت‌های شما هم به درستی قابل ترسیم و تعیین خواهد بود. این بدان دلیل است که مدل داده (Data Model) و رابط کاربری معمولا از یک معماری اطلاعات (information architecture) یکسان تبعیت میکنند. -رابط کاربری را طوری به کامپوننت های مختلف تقسیم کنید که هر کامپوننت با بخش خاصی از مدل داده مرتبط باشد. +رابط کاربری را طوری به کامپوننت‌های مختلف تقسیم کنید که هر کامپوننت با بخش خاصی از مدل داده مرتبط باشد. ![Component diagram](../images/blog/thinking-in-react-components.png) در این تصویر می بینید که ما پنج کامپوننت در برنامه خود داریم و اطلاعاتی که هر کامپوننت نمایش میدهد را با حروف ایتالیک مشخص کرده ایم: 1. **`FilterableProductTable` (نارنجی):** شامل تمام برنامه - 2. **`SearchBar` (آبی):** *ورودی های کاربر* را دریافت میکند + 2. **`SearchBar` (آبی):** *ورودی‌های کاربر* را دریافت میکند 3. **`ProductTable` (سبز):** تمامی *مجموعه اطلاعات* را با توجه به *ورودی کاربر* نمایش داده و اطلاعات را فیلتر میکند 4. **`ProductCategoryRow` (فیروزه ای):** یک تیتر را برای هر *دسته* نمایش میدهد 5. **`ProductRow` (قرمز):** یک ردیف را برای هر *محصول* نمایش میدهد -اگر نگاهی به کامپوننت `ProductTable`بیندازید، متوجه میشوید که تیترهای جدول (شامل "Name" و “Price”) کامپوننت جداگانه ای ندارند که بیشتر یک موضوع سلیقه ای است و دلایل و استدلال هایی برای استفاده یا عدم استفاده از یک کامپوننت جداگانه برای آنها وجود دارد. - +اگر نگاهی به کامپوننت `ProductTable`بیندازید، متوجه میشوید که تیترهای جدول (شامل "Name" و “Price”) کامپوننت جداگانه‌ای ندارند که بیشتر یک موضوع سلیقه‌ای است و دلایل و استدلال‌هایی برای استفاده یا عدم استفاده از یک کامپوننت جداگانه برای آنها وجود دارد. در این مثال، آن را بخشی از `ProductTable` قرار دادیم، چرا که جزئی از *مجموعه داده ها data collection* بوده و رندر کردن آن وظیفه `ProductTable` است. -با این حال، اگر هدر جدول پیچیده تر شود (مثلا اگر گزینه ای برای مرتب کردن لیست محصولات اضافه میکردیم)، مطمئنا منطقی تر بود که آنها در یک کامپوننت جداگانه با نام `ProductTableHeader` بگذاریم +با این حال، اگر هدر جدول پیچیده‌تر شود (مثلا اگر گزینه‌ای برای مرتب کردن لیست محصولات اضافه می‌کردیم)، مطمئنا منطقی‌تر بود که آنها در یک کامپوننت جداگانه با نام `ProductTableHeader` بگذاریم -حالا که کامپوننت های موجود در پروژه را مشخص کردیم، وقتش رسیده که سلسله مراتب آنها را نیز تعیین کنیم. کامپوننت هایی که با توجه به مدل، درون یک کامپوننت دیگر قرار میگیرند، فرزند آن محسوب میشوند: +حالا که کامپوننت‌های موجود در پروژه را مشخص کردیم، وقتش رسیده که سلسله مراتب آنها را نیز تعیین کنیم. کامپوننت‌هایی که با توجه به مدل، درون یک کامپوننت دیگر قرار می‌گیرند، فرزند آن محسوب می‌شوند: * `FilterableProductTable` * `SearchBar` @@ -75,55 +74,54 @@ prev: composition-vs-inheritance.html

این بخش را در فکر کردن در چارچوب ری‌اکت: گام دوم روی CodePen ببینید.

-بعد از اینکه سلسله مراتب را مشخص کردید، نوبت به پیاده سازی اپ میرسد. راحتترین راه این است که نسخه ای بسازید که مدل داده ها را میگیرد و رابط کاربری را تولید میکند اما هیچ تعاملی با کاربر ندارد. -بهتر است که این دو فرایند (نوشتن نسخه تعاملی و ایستا Static) را از هم جدا کنیم، به این دلیل که ساخت نسخه ایستا، به مقدار زیادی نوشتن و مقدار کمی فکر کردن نیاز دارد. اما اضافه کردن امکان تعامل و پویایی، احتیاج به مقدار زیادی تفکر دارد و نیاز آن به نوشتن بسیار کمتر است. دلیلش را در ادامه خواهیم دید. +بعد از اینکه سلسله مراتب را مشخص کردید، نوبت به پیاده‌سازی اپ میرسد. راحت‌ترین راه این است که نسخه‌ای بسازید که مدل داده ها را می‌گیرد و رابط کاربری را تولید می‌کند اما هیچ تعاملی با کاربر ندارد. +بهتر است که این دو فرایند (نوشتن نسخه تعاملی و ایستا) را از هم جدا کنیم، به این دلیل که ساخت نسخه ایستا، به مقدار زیادی نوشتن و مقدار کمی فکر کردن نیاز دارد. اما اضافه کردن امکان تعامل و پویایی، احتیاج به مقدار زیادی تفکر دارد و نیاز آن به نوشتن بسیار کمتر است. دلیلش را در ادامه خواهیم دید. -برای ساخت یک نسخه ایستا که مدل داده را رندر کند و نمایش دهد، باید کامپوننت هایی بسازید که از بقیه کامپوننت ها استفاده میکنند و داده ها را از طریق *props* انتقال میدهند. *Props* امکانی است که بوسیله آن، داده ها از کامپوننت والد parent به کامپوننت فرزند child منتقل میشوند. -اگر که با مفهوم state آشنایی دارید، **هرگز از آن برای ساخت نسخه ایستا استفاده نکنید!** State برای ایجاد تعامل طراحی شده و داده ای است که در طول زمان تغییر میکند و از آنجایی که فعلا روی نسخه ایستا کار میکنیم، نیازی به آن نخواهیم داشت. +برای ساخت یک نسخه ایستا که مدل داده را رندر کند و نمایش دهد، باید کامپوننت‌هایی بسازید که از بقیه کامپوننت‌ها استفاده میکنند و داده ها را از طریق *props* انتقال می‌دهند. *Props* امکانی است که بوسیله آن، داده‌ها از کامپوننت والد parent به کامپوننت فرزند child منتقل میشوند. +اگر که با مفهوم state آشنایی دارید، **هرگز از آن برای ساخت نسخه ایستا استفاده نکنید!** State برای ایجاد تعامل طراحی شده و داده‌ای است که در طول زمان تغییر میکند و از آنجایی که فعلا روی نسخه ایستا کار می‌کنیم، نیازی به آن نخواهیم داشت. -میتوانید روند ساخت را از بالا به پایین یا از پایین به بالا شروع کنید. به این معنا که هم میتوانید از بالاترین کامپوننت در سلسله مراتب آغاز کنید (مثلا `FilterableProductTable`) یا از کامپوننت هایی که در سطوح پایین تری قرار دارند (مثل `ProductRow`). در مثال ها ساده تر، معمولا شروع از بالا به پایین راحت تر است. در حالیکه در پروژه های بزرگتر، بهتر است که از پایین به بالا پیش بروید و همزمان با ساخت اپ، برای آن تست نیز بنویسید. +می‌توانید روند ساخت را از بالا به پایین یا از پایین به بالا شروع کنید. به این معنا که هم می‌توانید از بالاترین کامپوننت در سلسله مراتب آغاز کنید (مثلا `FilterableProductTable`) یا از کامپوننت‌هایی که در سطوح پایین‌تری قرار دارند (مثل `ProductRow`). در مثال‌های ساده‌تر، معمولا شروع از بالا به پایین راحت‌تر است. در حالیکه در پروژه‌های بزرگ‌تر، بهتر است که از پایین به بالا پیش بروید و همزمان با ساخت اپ، برای آن تست نیز بنویسید. -در پایان این گام، شما کتابخانه ای از کامپوننت ها خواهید داشت که مدل داده data model را رندر میکند. از آنجایی که با نسخه ایستا سر و کار داریم، کامپوننت ها تنها متد `render()` خواهند داشت. -کامپوننتی که در راس سلسله مراتب قرار دارد (یعنی `FilterableProductTable`) مدل داده ها را بعنوان یک prop دریافت میکند. -اگر تغییراتی را در مدل داده های زیربنایی پروژه ایجاد کنید و دوباره `ReactDOM.render()` را صدا بزنید، رابط کاربری به روز رسانی update خواهد شد و میتوانید ببینید که رابط کاربری چگونه و در کجا تغییر میکند. -**جریان یکطرفه داده one-way data flow** در ری‌اکت (که با نام *الزام و محدودیت یک طرفه one-way binding* نیز شناخته میشود) همه چیز را ماژولار و سریع نگه میدارد. +در پایان این گام، شما کتابخانه‌ای از کامپوننت‌ها خواهید داشت که مدل داده را رندر می‌کند. از آنجایی که با نسخه ایستا سر و کار داریم، کامپوننت‌ها تنها متد `render()` خواهند داشت. +کامپوننتی که در راس سلسله مراتب قرار دارد (یعنی `FilterableProductTable`) مدل داده‌ها را بعنوان یک prop دریافت می‌کند. +اگر تغییراتی را در مدل داده‌های زیربنایی پروژه ایجاد کنید و دوباره `ReactDOM.render()` را صدا بزنید، رابط کاربری بروز رسانی (update) خواهد شد و میتوانید ببینید که رابط کاربری چگونه و در کجا تغییر می‌کند. +**جریان یکطرفه داده one-way data flow** در ری‌اکت (که با نام *binding یک‌طرفه* نیز شناخته میشود) همه چیز را ماژولار و سریع نگه می‌دارد. اگر برای اجرای این بخش به کمک نیاز داشتید، به [React docs](/docs/) مراجعه کنید. ### یک مکث مختصر: props در مقابل state {#a-brief-interlude-props-vs-state} -دو نوع داده "نمونه" (model) در ری¬اکت وجود دارد و خیلی مهم است که تفاوت این دو را بدانیم: اگر خیلی در این مورد مطمئن نیستید، نگاهی به [مستندات رسمی ری‌اکت ](/docs/state-and-lifecycle.html) بیندازید. -علاوه براین، میتوانید به بخش [سوالات پرتکرار: تفاوت میان state و props چیست؟](/docs/faq-state.html#what-is-the-difference-between-state-and-props) مراجعه کنید. - -## قدم سوم: مشخص کردن یک نمونه حداقلی اما کامل از state های موردنیاز در رابط کاربری {#step-3-identify-the-minimal-but-complete-representation-of-ui-state} +دو نوع داده "نمونه" (model) در ری‌اکت وجود دارد و خیلی مهم است که تفاوت این دو را بدانیم: اگر خیلی در این مورد مطمئن نیستید، نگاهی به [مستندات رسمی ری‌اکت ](/docs/state-and-lifecycle.html) بیندازید. +علاوه بر این، می‌توانید به بخش [سوالات پرتکرار: تفاوت میان state و props چیست؟](/docs/faq-state.html#what-is-the-difference-between-state-and-props) مراجعه کنید. -برای تعاملی کردن رابط کاربری، باید بتوانید در مدل داده زیربنایی پروژه (همان داده¬های اولیه) تغییر ایجاد کنید. اینکار در ری¬اکت از طریق **state** انجام میشود. +## قدم سوم: مشخص کردن یک نمونه حداقلی (اما کامل) از state های موردنیاز در رابط کاربری {#step-3-identify-the-minimal-but-complete-representation-of-ui-state} -برای ساخت اپ به صورت صحیح، ابتدا باید به مجموعه ای حداقلی از داده های قابل تغییر فکر کنید که در پروژه شما نیاز است. کلید این موضوع، [اصل *خودت را تکرار نکن*](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) است. +برای تعاملی کردن رابط کاربری، باید بتوانید در مدل داده زیربنایی پروژه [همان داده‌های اولیه] تغییر ایجاد کنید. اینکار در ری‌اکت از طریق **state** انجام میشود. +برای ساخت اپ به صورت صحیح، ابتدا باید به مجموعه‌ای حداقلی از داده‌های قابل تغییر فکر کنید که در پروژه شما نیاز است. کلید این موضوع، [اصل *خودت را تکرار نکن*](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) است. تعیین کنید که در حال حاضر، مختصرترین مجموعه state که برنامه شما نیاز دارد چیست و بقیه موارد را به مرور، و در زمان لزوم محاسبه و تعیین کنید. -برای مثال، اگر یک برنامه برای لیست کارها TODO List طراحی میکنید، یک آرایه array از آیتم های موجود در لیست کارها را در دسترس نگه دارید. اما دیگر نیازی به تعیین یک state برای شمارش آیتم ها ندارید. به جای آن، زمان رندر کردن تعداد، میتوانید از طول آرایه آیتم ها (Array.length) استفاده کنید. +برای مثال، اگر یک برنامه برای لیست کارها (TODO List) طراحی میکنید، یک آرایه از آیتم‌های موجود در لیست کارها را در دسترس نگه دارید. اما دیگر نیازی به تعیین یک state برای شمارش آیتم‌ها ندارید. به جای آن، زمان رندر کردن تعداد، میتوانید از طول آرایه آیتم‌ها (Array.length) استفاده کنید. تمام بخش های داده در مثال خودمان را در نظر بگیرید: * یک لیست اصلی از محصولات * متنی که کاربر جستجو میکند - * مقدار (value) چک باکس + * مقدار checkbox * لیست محصولات فیلتر شده پس از جستجو توسط کاربر -به طور جداگانه سراغ هر یک از این موارد میرویم تا ببینیم که کدامشان state هستند. درمورد هر بخش، این 3 سوال را از خودتان بپرسید: +به طور جداگانه سراغ هر یک از این موارد می‌رویم تا ببینیم که کدامشان state هستند. درمورد هر بخش، این 3 سوال را از خودتان بپرسید: 1. آیا این داده از طرف یک کامپوننت والد و بوسیله props انتقال داده شده؟ اگر جواب مثبت است، پس احتمالا این داده state نیست. 2. آیا در طول زمان بدون تغییر می ماند؟ اگر اینطور است پس احتمالا باز هم state نیست. - 3. آیا میتوانید آن را بر اساس یک state یا props موجود محاسبه کنید؟ (مثل همان طول لیست کارها!) اگر اینطور است، پس حتما این داده state نیست. + 3. آیا میتوانید آن را بر اساس یک state یا props موجود محاسبه کنید؟ اگر اینطور است، پس حتما این داده state نیست. -لیست اولیه و اصلی محصولات، بعنوان یک props منتقل میشود، بنابراین state نیست. اما به نظر میرسد که متن جستجو و مقدار چک باکس state هستند چرا که در طول زمان تغییر میکنند و نمیتوان آن ها را بوسیله داده دیگری محاسبه کرد. در نهایت، لیست محصولات فیلتر شده پس از جستجو هم state نیست، چرا که میتوان آن را از ترکیب لیست اصلی و اولیه با متن سرچ کاربر و مقدار چک باکس بدست آورد. +لیست اولیه و اصلی محصولات، بعنوان یک props منتقل میشود، بنابراین state نیست. اما به نظر میرسد که متن جستجو و مقدار چک باکس state هستند چرا که در طول زمان تغییر میکنند و نمی‌توان آن‌ها را بوسیله داده دیگری محاسبه کرد. در نهایت، لیست محصولات فیلتر شده پس از جستجو هم state نیست، چرا که می‌توان آن را از ترکیب لیست اصلی و اولیه با متن سرچ کاربر و مقدار چک باکس بدست آورد. پس در مجموع، state این اپ عبارتند از: * متنی که کاربر در فیلد جستجو وارد میکند - * مقدار (value) چک باکس + * مقدار checkbox ## قدم چهارم: مشخص کنید که state در کجا باید قرار بگیرد {#step-4-identify-where-your-state-should-live} @@ -131,14 +129,14 @@ prev: composition-vs-inheritance.html بعد از اینکه ما حداقل state مورد نیاز در پروژه را مشخص کردیم، نوبت این است که بدانیم هر state باید در کدام کامپوننت قرار بگیرد. -به یاد داشته باشید: ری¬اکت بر مبنای جریان یک طرفه و رو به پایین داده در سلسله مراتب کامپوننت ها کار میکند. ممکن است این موضوع که کدام کامپوننت، کدام state را در خود جا میدهد، فورا مشخص و واضح نباشد. **اغلب این مساله، چالش برانگیزترین بخش برای افرادیست که تازه با ری‌اکت آشنا شده اند.** +به یاد داشته باشید: ری‌اکت بر مبنای جریان یک طرفه و رو به پایین داده در سلسله مراتب کامپوننت‌ها کار می‌کند. ممکن است این موضوع که کدام کامپوننت، کدام state را در خود جا می‌دهد، فورا مشخص و واضح نباشد. **اغلب این مساله، چالش برانگیزترین بخش برای افرادیست که تازه با ری‌اکت آشنا شده اند.** پس برای اینکه متوجه موضوع بشوید، این قدم ها را برای هر state در برنامه خود دنبال کنید: - * کامپوننت هایی را که چیزی را براساس آن state رندر میکنند، مشخص کنید. - * یک کامپوننت مشترک صاحب state را پیدا کنید (کامپوننتی که در سلسله مراتب برنامه، بالاتر از دیگر کامپوننت های استفاده کننده از state قرار میگیرد و خود نیز از آن state استفاده میکند) - * صاحب مشترک یا کامپوننت دیگری که در سلسله مراتب، بالاتر قرار میگیرد، باید صاحب state باشند. - * اگر نتوانستید کامپوننتی را پیدا کنید که قرار دادن state در آن منطقی باشد، یک کامپوننت جدید ایجاد کنید که منحصرا برای نگهداری state باشد و آن را جایی بالاتر از صاحب مشترک state (در سلسله مراتب کامپوننت ها) قرار دهید. + * کامپوننت‌هایی را که چیزی را براساس آن state رندر می‌کنند، مشخص کنید. + * یک کامپوننت مشترک صاحب state را پیدا کنید (کامپوننتی که در سلسله مراتب برنامه، بالاتر از دیگر کامپوننت‌های استفاده کننده از state قرار می‌گیرد و خود نیز از آن state استفاده می‌کند) + * صاحب مشترک یا کامپوننت دیگری که در سلسله مراتب، بالاتر قرار می‌گیرد، باید صاحب state باشند. + * اگر نتوانستید کامپوننتی را پیدا کنید که قرار دادن state در آن منطقی باشد، یک کامپوننت جدید ایجاد کنید که منحصرا برای نگهداری state باشد و آن را جایی بالاتر از صاحب مشترک state [در سلسله مراتب کامپوننت‌ها] قرار دهید. حالا این استراتژی را برای برنامه خودمان اجرا کنیم: @@ -148,29 +146,29 @@ prev: composition-vs-inheritance.html به این ترتیب، در ابتدا ویژگی `this.state = {filterText: '', inStockOnly: false}` را در بخش `constructor`در کامپوننت `FilterableProductTable` قرار میدهیم تا state ابتدایی برنامه شما را نشان دهد. -سپس، `filterText` و `inStockOnly` را به کامپوننت های `ProductTable` و `SearchBar` بعنوان props انتقال میدهیم. -درنهایت، این props برای فیلتر ردیف های محصولات در `ProductTable` و مشخص کردن مقدار در چک باکس موجود در `SearchBar` به کار میروند. +سپس، `filterText` و `inStockOnly` را به کامپوننت‌های `ProductTable` و `SearchBar` بعنوان props انتقال می‌دهیم. +درنهایت، این props برای فیلتر وردی های محصولات در `ProductTable` و مشخص کردن مقدار در چک باکس موجود در `SearchBar` به کار می‌روند. -حالا میتوانید ببینید که برنامه شما چطور عمل میکند: `filterText` را به `"ball"` تغییر بدید و برنامه را دوباره بارگذاری (refresh) کنید. خواهید دید که جدول داده ها به درستی تغییر میکند. +حالا می‌توانید ببینید که برنامه شما چطور عمل می‌کند: `filterText` را به `"ball"` تغییر بدهید و برنامه را دوباره بارگذاری (refresh) کنید. خواهید دید که جدول داده‌ها به درستی تغییر می‌کند. ## قدم پنجم: اضافه کردن جریان معکوس داده {#step-5-add-inverse-data-flow}

این بخش را در فکر کردن در چارچوب ری‌اکت: گام پنجم در CodePen ببینید.

-تا به اینجای کار، ما برنامه ای ساختیم که به طور صحیح و به شکل تابعی از props و state، رندر میشد و جریان داده در آن از بالا به پایین بود. -اما حالا زمان آن است که برنامه، جریان داده را به شکل معکوس و رو به بالا پشتیبانی کند: فرم های موجود در پایین ترین بخش سلسله مراتب کامپوننت ها، باید بتوانند state درون کامپوننت `FilterableProductTable` را تغییر دهند. +تا به اینجای کار، ما برنامه‌ای ساختیم که به طور صحیح و به شکل تابعی از props و state، رندر می‌شد و جریان داده در آن از بالا به پایین بود. +اما حالا زمان آن است که برنامه، جریان داده را به شکل معکوس و رو به بالا پشتیبانی کند: فرم‌های موجود در پایین‌ترین بخش سلسله مراتب کامپوننت‌ها، باید بتوانند state درون کامپوننت `FilterableProductTable` را تغییر دهند. -ری‌اکت، این جریان داده را ساده و شفاف میکند تا به کمک آن، بتوانید طرز کار برنامه تان را درک کنید، اما این مساله احتیاج به نوشتن و تایپ بیشتری نسبت به data binding دو طرفه و مرسوم دارد. +ری‌اکت، این جریان داده را ساده و شفاف میکند تا به کمک آن، بتوانید طرز کار برنامه‌تان را درک کنید، اما این مساله احتیاج به نوشتن و تایپ بیشتری نسبت به data binding دو طرفه و مرسوم دارد. -اگه در فیلد جستجو تایپ کنید یا مقدار چک باکس را تغییر دهید (تیک آن را فعال کنید) خواهید که ری‌اکت، این تغییرات را نادیده میگیرد. این موضوع عمدی است، چرا که ما تعیین کردیم، `value` در `input` همواره با مقدار `state` که از کامپوننت `FilterableProductTable` منتقل میشود، برابر باشد. +اگه در فیلد جستجو تایپ کنید یا مقدار چک باکس را تغییر دهید [تیک آن را فعال کنید] خواهید دید که ری‌اکت، این تغییرات را نادیده می‌گیرد. این موضوع عمدی است، چرا که ما تعیین کردیم، `value` در `input` همواره با مقدار `state` که از کامپوننت `FilterableProductTable` منتقل می‌شود، برابر باشد. -بیایید به این فکر کنیم که میخواهیم چه اتفاقی بیفتد؟ میخواهیم مطمئن شویم که هر زمان کاربر، تغییراتی را در فرم (فیلد جستجو یا چک باکس) اعمال میکند، state به روز رسانی شده و تغییرات را منعکس کند. -از آنجایی که کامپوننت ها فقط مجاز به تغییر state موجود در خودشان هستند، کامپوننت `FilterableProductTable` کال بک هایی (callback) را به کامپوننت`SearchBar` انتقال میدهد تا هر وقت نیاز به تغییر state وجود داشت، اجرا شوند. -میتوانیم از رویداد `onChange` برای ورودی ها استفاده کنیم تا به این طریق، کامپوننت `FilterableProductTable` از لزوم اجرای تغییر مطلع شود. -آن کال بک که از کامپوننت `FilterableProductTable` انتقال می یابد، `setState()` است و باعث تغییر و به روز رسانی (update) اپ میشود. +بیایید به این فکر کنیم که می‌خواهیم چه اتفاقی بیفتد؟ می‌خواهیم مطمئن شویم که هر زمان کاربر، تغییراتی را در فرم (فیلد جستجو یا چک باکس) اعمال می‌کند، state بروز رسانی شده و تغییرات را منعکس کند. +از آنجایی که کامپوننت‌ها فقط مجاز به تغییر state موجود در خودشان هستند، کامپوننت `FilterableProductTable` کال‌بک‌هایی (callback) را به کامپوننت`SearchBar` انتقال می‌دهد تا هر وقت نیاز به تغییر state وجود داشت، اجرا شوند. +می‌توانیم از رویداد `onChange` برای ورودی‌ها استفاده کنیم تا به این طریق، کامپوننت `FilterableProductTable` از لزوم اجرای تغییر مطلع شود. +آن کال‌بک که از کامپوننت `FilterableProductTable` انتقال می‌یابد، `setState()` است و باعث تغییر و بروز رسانی اپ میشود. ## همین! {#and-thats-it} -امیدواریم که این مطلب، به شما ایده داده باشد که چگونه باید درباره ساختن کامپوننت ها و برنامه ها در ری¬اکت فکر کنید. البته ممکن است که میزان نوشتن، بیشتر از حدی باشد که به آن عادت دارید، اما به یاد داشته باشید که کد، بیشتر از اینکه نوشته شود، خوانده میشود و خواندن این کد که شکل ماژولار، ساده و شفاف نوشته شده است، بسیار راحت تر خواهد بود. +امیدواریم که این مطلب، به شما ایده داده باشد که چگونه باید درباره ساختن کامپوننت‌ها و برنامه‌ها در ری‌اکت فکر کنید. البته ممکن است که میزان نوشتن، بیشتر از حدی باشد که به آن عادت دارید، اما به یاد داشته باشید که کد، بیشتر از اینکه نوشته شود، خوانده می‌شود و خواندن این کد که به شکل ماژولار، ساده و شفاف نوشته شده است، بسیار راحت‌تر خواهد بود. -به محض اینکه ساخت کتابخانه های بزرگ متشکل از کامپوننت ها را شروع کنید، بابت این شفافیت و ماژولار بودن سپاسگزار خواهید شد، و با وجود امکان استفاده مجدد از کدها، تعداد خطوط کد شما، شروع به آب رفتن میکند و کوچکتر و کوتاه تر خواهند شد! :) \ No newline at end of file +به محض اینکه ساخت کتابخانه‌های بزرگ متشکل از کامپوننت‌ها را شروع کنید، بابت این شفافیت و ماژولار بودن سپاسگزار خواهید شد، و با وجود امکان استفاده مجدد از کدها، تعداد خط‌های کد شما به مرور کم‌تر خواهد شد! :) \ No newline at end of file From 2aa4e60897a4679feb6f567e1f68eb3ea3364e32 Mon Sep 17 00:00:00 2001 From: Erfan <52595036+rfnmt@users.noreply.github.com> Date: Sun, 19 Jan 2020 16:23:46 +0330 Subject: [PATCH 5/5] Improvement --- content/docs/hooks-intro.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/hooks-intro.md b/content/docs/hooks-intro.md index f04be9fd6..7c0d85210 100644 --- a/content/docs/hooks-intro.md +++ b/content/docs/hooks-intro.md @@ -54,7 +54,7 @@ function Example() { **اگر هم‌‌اکنون می‌‌خواهید یادگیری هوک‌‌ها را شروع کنید، [مستقیم به صفحه‌‌ی بعد بروید!](/docs/hooks-overview.html)** البته می‌‌توانید مطالعه‌‌ این صفحه را ادامه دهید و با دلایلی که هوک‌‌ها را به ری‌‌اکت اضافه کردیم و اینکه چگونه بدون بازنویسی اپلیکیشن‌‌های قبلی از آن‌‌ها استفاده خواهیم کرد، آشنا شوید. -## انگیزه {#انگیزه} +## انگیزه هوک‌ها مشکلات مختلفی که ظاهرا به هم ارتباط ندارند را حل می‌کنند. مواردی که ما طی در نوشتن و نگهداری هزاران کامپوننت طی پنج سال با آن مواجه شده‌ایم. اگر درحال یادگیری ری‌اکت هستید، هروز از آن استفاده می‌کنید یا از کتابخانه مشابهی استفاده می‌کنید که بر پایه کامپوننت طراحی شده‌است، احتمالا به این مشکلات بر خورد کرده‌اید.