diff --git a/content/docs/thinking-in-react.md b/content/docs/thinking-in-react.md index 3e054806a..e8e917fde 100644 --- a/content/docs/thinking-in-react.md +++ b/content/docs/thinking-in-react.md @@ -8,17 +8,18 @@ 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. +React, לפי דעתנו, היא ספריית הג'וואה-סקריפט המובילה בבניית יישומי אינטרנט. הספרייה הוכיחה את עצמה אצלנו בפייסבוק ובאינסטגרם. -## Start With A Mock {#start-with-a-mock} +אחד מהיתרונות הבולטים של React הוא איך הוא גורם לך לחשוב על היישומים בזמן שאתה בונה אותם. במדריך זה, נלווה אותך בתהליך החשיבה של בניית טבלת נותני מוצרים באמצעות React. -Imagine that we already have a JSON API and a mock from our designer. The mock looks like this: +## נתחיל עם דוגמא{#start-with-a-mock} + +נניח שיש לנו ממשק JSON שנראה ככה: ![Mockup](../images/blog/thinking-in-react-mock.png) -Our JSON API returns some data that looks like this: +הממשק מחזיר מידע בפורמט JSON שנראה ככה: ``` [ @@ -31,27 +32,30 @@ 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? Just 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. +אבל איך יודעים מה צריך להיות קומפוננטה משלו? משתמשים באותה טכניקה שבה מחליטים אם ליצור מתודה או עצם. +אחת השיטות היא [עיקרון האחריות הבודדת](https://en.wikipedia.org/wiki/Single_responsibility_principle), שאומר, שאופן אידיאלי כל קומפוננטה אמורה לעשות דבר אחד בלבד. אם הקומפוננטה גדלה, נצטרך לפצל אותה לתת-קומפוננטות. -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*, which means the work of separating your UI into components is often trivial. Just break it up into components that represent exactly one piece of your data model. +משום שלעיתים תכופות נצטרך להציג מידע בפורמט JSON למשתמש, נראה שאם המודל נבנה כראוי, ממשק המשתמש שלנו( וגם מבנה הקומפוננטות ) ימופה באופן מסודר. זה קורה מכיוון שממשק המשתמש ומודלי המידע נוטים לדבוק באותה *ארכיטקטורת מידע*, מה שאומר שפיצול ממשק המשתמש לקומפוננטות הוא לעיתים טריוויאלי. רצוי לפצל את ממשק המשתמש לקומפוננטות שכל אחת מייצגת פיסה אחת של מודל המידע ![Component diagram](../images/blog/thinking-in-react-components.png) -You'll see here that we have five components in our simple app. We've italicized the data each component represents. +נראה כאן שיש לנו חמישה קומפוננטות ביישום הפשוט שלנו. המידע שכל קומפוננטה מייצגת הוא בפונט italic - 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 (i.e. if we were to add affordances for sorting), it would certainly make sense to make this its own `ProductTableHeader` component. +אם נסתכל על ProductTable, נראה שכותרת הטבלה( שמכילה את כותרות השם והמחיר ) היא לא קומפוננטה משלה. אפשר להפוך אותה לקומפוננטה משלה ואפשר גם שלא, זה עניין של בחירה. +בדוגמה זאת, השארנו אותו חלק מProductTable בגלל שזה חלק מרינדור *המידע*, שהוא עבודת הקומפוננטה ProductTable. +לעומת זאת, אם הכותרת גדלה ונהיית מסובכת( לדוגמה אם היינו מוסיפים חיפוש ), זה בהחלט יעלה צורך לפצל אותה לקומפוננטה משלה( ProductTableHeader ). +עכשיו לאחר שזיהינו את הקומפוננטות בדוגמה שלנו, נסדר אותם בהיררכיה. קומפוננטות שנמצאות בתוך קומפוננטות אחרות צריכות להופיע מתחתיהן בהיררכיה: -Now that we've identified the components in our mock, let's arrange them into a hierarchy. This is easy. Components that appear within another component in the mock should appear as a child in the hierarchy: * `FilterableProductTable` * `SearchBar` @@ -59,90 +63,92 @@ 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} +## Step 2: בניית גרסה סטטית בReact {#step-2-build-a-static-version-in-react}

See the Pen Thinking In React: Step 2 on 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. +עכשיו שיש לנו את היררכיית הקומפוננטות שלנו, זה הזמן ליישם את היישום. הדרך הקלה ביותר היא לבנות גרסה שלוקח את מודל המידע ומרנדרת את ממשק המשתמש, אבל אין לה אינטראקטיביות. מומלץ לפצל תהליכים אלו בגלל שבניית גרסה סטטית דורשת הרבה הקלדה ומינימום חשיבה, והוספת אינטראקטיביות דורשת הרבה חשיבה ומינימום הקלדה. נראה למה. -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. +על מנת לבנות גרסה סטטית של היישום שמרנדרת את מודל המידע, נרצה לבנות קומפוננטות שמשתמשות בקומפוננטות אחרות ומעבירות מידע באמצעות props**.*props* הם דרך העברת מידע מ'הורה' ל'ילד'. אם אתם מכירים את הקונספט של *state*, **אל תשתמשו בstate בכלל** על מנת לבנות את הגרסה הסטטית. state שמור רק לאינטראקטיביות, שזה מידע שמשתנה לאורך זמן. מכיוון שזאתי גרסה סטטית של היישום, לא נצטרך state. -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. +נוכל לבנות מלמעלה למטה או מלמטה למעלה. שזה אומר שנוכל להתחיל לבנות את הקומפוננטות מלמעלה בהירככיה( נתחיל מFilterableProductTable ) או מהקומפוננטות התחתונות בהיררכיה( ProductRow ). בדוגמות פשוטות יותר, זה קל יותר להתחיל מלמעלה למטה, ובפרויקטים גדולים, זה קל יותר להתחיל מלמטה למעלה ולכתוב tests במקביל לבנייה. -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. It's easy to see how your UI is updated and where to make changes since there's nothing complicated going on. React's **one-way data flow** (also called *one-way binding*) keeps everything modular and fast. +בסוף השלב הזה, יהיה לנו ספרייה של קומפוננטות שמישות שמרנדרות את מודל המידע. הקומפוננטות יכילו רק מתודות render() מכיון שזוהי גרסה סטטית של היישום. הקומפוננטה בראש ההיררכיה(FilterableProductTable) תיקח את מודל המידע כprop שיועבר לה. אם נבצע שינוי למודל המידע ונקרא ל ReactDOM.render() שוב, ממשק המשתמש יעודכן. זה פשוט לראות איך ממשק המשתמש מעודכן והיכן לבצע שינויים מכיוון ששום דבר מסובך לא מתבצע. **העברת המידע בכיוון אחד** של React משאירה הכל בצורה מודולרית ומהירה. -Simply refer to the [React docs](/docs/) if you need help executing this step. +קרא עוד ב[תיעוד של ריאקט](/docs/) אם תצטרך עזרה בביצוע שלב זה. -### A Brief Interlude: Props vs State {#a-brief-interlude-props-vs-state} +### הפוגה קצרה: props ו- state {#a-brief-interlude-props-vs-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/interactivity-and-dynamic-uis.html) if you aren't sure what the difference is. +יש שני סוגים של 'מודלי' מידע בReact : props וstate. זה חשוב להבין את ההבדלים בין השניים. קרא עוד [בתיעוד של ריאקט](/docs/interactivity-and-dynamic-uis.html) אם אתה לא בטוח מה ההבדל. -## Step 3: Identify The Minimal (but complete) Representation Of UI State {#step-3-identify-the-minimal-but-complete-representation-of-ui-state} +## שלב שלישי: זיהוי הייצוג המינימלי( אך מלא ) של הstate של ממשק המשתמש {#step-3-identify-the-minimal-but-complete-representation-of-ui-state} -To make your UI interactive, you need to be able to trigger changes to your underlying data model. React makes this easy with **state**. +על מנת שממשק המשתמש יהיה אינטראקטיבי, נצטרך שיהיה לנו את היכולת לשנות את מודל המידע שלנו. React עושה את זה בצורה פשוטה עם **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, just 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, simply take the length of the TODO items array. +כדי לבנות את היישום בצורה נכונה, צריך לחשוב תחילה על הכמות המינימלית של state שהיישום דורש. המפתח פה הוא [DRY: *Don't Repeat Yourself*](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself) שאומר 'אל תמחזר קוד'. נחשוב על הכמות המינימלית ביותר של state שהיישום צריך ונחשב כל דבר אחר שהיישום צריך לפי דרישה. לדוגמה, אם אנו בונים יישום של רשימת מטלות, יהיה לנו מערך של מטלות; לא נשאיר משתנה בstate בשביל הכמות מטלות. במקום זה, כשנרצה לרנדר את מספר המטלות, פשוט ניקח את אורך המערך ונציג אותו. -Think of all of the pieces of data in our example application. We have: +נראה את פיסות המידע ביישום שלנו, יש לנו את: - * The original list of products - * The search text the user has entered - * The value of the checkbox - * The filtered list of products + * הרשימה המקורית של המוצרים + * מילות החיפוש שהמשתמש הקליד + * ערך תיבת הסימון + * הרשימה המסוננת של המוצרים -Let's go through each one and figure out which one is state. Simply ask three questions about each piece of data: +נעבור על כל אחד ונחשוב איזה פיסת מידע היא הstate. נעשה זאת באמצעות שאילת 3 שאלות על כל פיסת מידע: - 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. + 1. האם המידע עובר מהורה באמצעות props? אם כן, זה לא state. + 2. האם זה נשאר קבוע לאורך זמן? אם כן, זה לא state. + 3. האם אפשר לחשב את זה לפי state אחר או props בקומפוננטה שלנו? אם כן, זה לא 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. +הרשימה המקורית עוברת באמצעות props, אז היא לא הstate. טקסט החיפוש ותיבת הסימון נראים כמתאימים להיות state מכיוון שהם משתנים לאורך זמן ולא מושפעים ממשהו. ולבסוף, הרשימה המסוננת של המוצרים היא לא הstate מכיוון שהיא מושפעת מהרשימה המקורית של המוצרים, טקסט החיפוש וערך תיבת הסימון( מסומן או לא). -So finally, our state is: +אז הגענו למסקנה שהstate שלנו הוא: - * The search text the user has entered - * The value of the checkbox + * טקסט החיפוש שהמשתמש הקליד + * ערך תיבת הסימון -## Step 4: Identify Where Your State Should Live {#step-4-identify-where-your-state-should-live} +## שלב רביעי: זיהוי המיקום המתאים לstate {#step-4-identify-where-your-state-should-live}

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

-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 של היישום שלנו. עכשיו אנחנו צריכים לזהות איזה קומפוננטה משנה, או לוקחת *בעלות* על הstate. + +זכרו: בReact הכל סובב סביב העברת מידע למטה בהיררכיית הקומפוננטות. זה לפעמים לא ברור מיד איזה קומפוננטה הכי מתאימה לאחסן בתוכה state. **זה לעיתים קרובות החלק הכי מאתגר למתחילים ב**React, לכן נעבור על השלבים הבאים על מנת להבין: -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 ביישום: -For each piece of state in your application: + * נזהה כל קומפוננטה שמרנדרת משהו מהstate. + * נמצא אם יש קומפוננטה אחרת למעלה בהיררכיה או קומפוננטה דומה שמתאימה לאחסן את הstate. + * אם לא נמצא קומפוננטה שמתאימה לאחסן את הstate, ניצור אחת חדשה שכל מטרתה היא לאחסן את הstate ונכניס אותה איפשהו בהיררכיה מעל קומפוננטה אחרת שמשתמשת בstate. - * 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 simply for holding the state and add it somewhere in the hierarchy above the common owner component. +נשתמש בשלבים אלה ביישום: -Let's run through this strategy for our application: + * ProductTable צריכה לסנן את רשימת המוצרים לפי הstate וSearchBar צריך להציג את טקסט החיפוש ותיבת הסימון. + * הקומפוננטה השנייה שעושה שימוש בstate היא FilterableProductTable. + * באופן עקרוני זה הגיוני שהטקסט המסונן והערך המסומן 'יחיו' בתוך FilterableProductTable. - * `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` +אז החלטנו שהstate 'חי' בתוך FilterableProductTable. ראשית, נוסיף אובייקט this.state = {filterText: '', inStockOnly: false} לFilterableProductTable קונסטרקטור שלו על מנת לשקף את הstate הראשוני של היישום. +אחרי זה, נעביר את filterText וinStockOnly לProductTable ו SearchBar כprop. +לבסוף, נשתמש ב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`. -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. +אפשר כבר להתחיל לראות איך היישום שלנו יתנהג: נגדיר את filterText ל''כדור'' ונרענן את היישום. נראה שטבלת המידע מתעדכנת עם הערך הנכון. -## Step 5: Add Inverse Data Flow {#step-5-add-inverse-data-flow} +## שלב חמישי: הוספת זרימת מידע הפוכה {#step-5-add-inverse-data-flow}

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

-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`. +עד כה, בנינו יישום שמרנדר כפונקציה של props וstate למטה בהיררכיה. עכשיו זה הזמן להוסיף אמצעי לזרימה הפוכה של מידע: קומפוננטות הטופס עמוק בהירככיה צריכות לעדכן את הstate בFilterableProductTable. -React makes this data flow explicit to make it easy to understand how your program works, but it does require a little more typing than traditional two-way data binding. +React הופך את זרימת המידע למפורשת על מנת שיהיה קל להבין איך היישום שלנו עובד, אבל זה דורש טיפה יותר שורות קוד מאשר binding דו כיווני של נתונים. -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`. +אם ננסה לכתוב או לסמן את הקופסה בגרסה הנוכחית של היישום שלנו, נראה שReact מתעלם מהקלט שלנו. זה נעשה בכוונה, מכיוון שאנחנו הגדרנו את ערך הprop של הקלט להיות תמיד שווה לstate שמועבר מFilterableProductTable. -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. +נחשוב לרגע על מה אנחנו רוצים שיקרה. אנחנו רוצים להיות בטוחים שכשהמשתמש משנה את הטופס, אנחנו מעדכנים את הstate שישקף את קלט המשתמש. מכיוון שרצוי שקומפוננטות יעדכנו את הstate שלהן בלבד, FilterableProductTable יעביר callbacks לSearchBar שיופעלו כשהstate יתעדכן. אנחנו יכולים להשתמש בonChange event על הקלטים. הcallbacks שעוברים דרך FilterableProductTable יקראו למתודת setState(), והיישום יתעדכן. -Though this sounds complex, it's really just a few lines of code. And it's really explicit how your data is flowing throughout the app. +אפילו שזה נשמע מסובך, זה בסך הכל מספר מצומצם של שורות קוד. והיתרון הוא שזה מציג באופן מפורש איך המידע מועבר ביישום. -## And That's It {#and-thats-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 extremely easy 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. :) +הכוונה של המדריך הזה היא לתת לכם רעיון על איך לחשוב על בניית קומפוננטות ויישומים עם React. אמנם זה יכול לצרוך יותר כתיבה ממה שאתם רגילים, אבל זכרו שקוד נקרא יותר מאשר הוא נכתב, וזה נוח מאוד לקרוא את הקוד המפורש והמודולרי שכתבנו. כשתתחילו לבנות ספריות גדולות של קומפוננטות, אתם תעריכו את הפשטות והמודולריות, ועם שימוש חוזר בקוד שאתם רושמים, שורות הקוד שלכם יתחילו להתכווץ. 😊