From 6615fe424cbb67e648f42749a093b4baa4d18e63 Mon Sep 17 00:00:00 2001 From: Marichka Tsiuriak Date: Mon, 11 Feb 2019 14:42:38 -0500 Subject: [PATCH 01/13] translate Thinking in React --- content/docs/thinking-in-react.md | 134 +++++++++++++++--------------- 1 file changed, 67 insertions(+), 67 deletions(-) diff --git a/content/docs/thinking-in-react.md b/content/docs/thinking-in-react.md index 3e054806a..1dc7f7150 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: Мыслить в React permalink: docs/thinking-in-react.html redirect_from: - 'blog/2013/11/05/thinking-in-react.html' @@ -8,17 +8,17 @@ 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. +По нашему мнению, React является ведущей технологией в построении больших, быстрых веб-приложений на основе JavaScript. Показателем этого есть успешная работа Facebook и 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} +## Взглянем на макет {#start-with-a-mock} -Imagine that we already have a JSON API and a mock from our designer. The mock looks like this: +Представьте, что у вас уже есть JSON API и макет дизайна сайта. Вот как он выглядит: ![Mockup](../images/blog/thinking-in-react-mock.png) -Our JSON API returns some data that looks like this: +Наш JSON API возвращает вот такие вот данные: ``` [ @@ -31,27 +31,27 @@ 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} +## Шаг 1: Разбиваем пользовательский интерфейс на составляющие{#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! +Первое, что нужно сделать — очертить границы вокруг каждого компонента (и подкомпонента) в макете и дать им имена. Если вы работаете в паре с дизайнером, вполне возможно, что он уже сделал это за вас. Так, слои в Photoshop отлично подходят для наименования React-компонентов. -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://ru.wikipedia.org/wiki/Принцип_единственной_ответственности), суть которого состоит в том, что в идеале компонент должен выполнять только одну поставленную задачу. Если в конечном итоге функционал компонента увеличивается, его следует разбить на более мелкие подкомпоненты. -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 пользователю, вы обнаружите, что если ваша модель была построена правильно, то пользовательский интерфейс (а следовательно и структура компонентов) отобразятся надлежащим образом. Это связано с тем, что UI и модели данных имеют свойство соблюдать аналогичную *информационную архитектуру*, а это в свою очередь значит, что разделять интерфейс на составляющие не имеет смысла. Просто разбейте его на компоненты, которые будут отображать одну конкретную модель данных. ![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. +Здесь мы видим, что наше простое приложение состоит из пяти различных компонентов. Курсивом выделены данные, которые эти компоненты представляють. - 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` несложно заметить, что заголовок таблицы ("Name" и "Price") сам по себе отдельным компонентом не является. Отделять его или нет — вопрос личного предпочтения, существует ряд аргументов как за, так и против. В данном примере мы решили не придавать этому особого значения и оставить заголовок частью большего компонента `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 +59,90 @@ 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} +## Шаг 2: Создаем статическую версию в React {#step-2-build-a-static-version-in-react} -

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

+

Пример кода Мыслить в React: Шаг 2 на 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. +Чтобы построить статическую версию приложения, отображающую модель данных, нам нужно создать компоненты, которые используют другие компоненты и передают данные через *пропсы*. *Пропсы* — это способ передачи данных от родителя к потомку. Если вы знакомы с понятием *состояния*, то для статической версии это как раз то, чего вам **использовать не нужно**. Состояние подразумевает собой данные, которые меняются со временем, что и есть интерактивностью. Так как мы работаем над статической версией приложения, нам этого не нужно. -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`). Более простые приложения удобнее начать с компонентов, находящихся выше по иерархии, в более сложных приложениях лучшей практикой в первую очередь считается создание и тестирование подкомпонентов. -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`) будет передавать модель данных через пропсы. Если вы внесете изменения в базовую модель данных и снова вызовете `ReactDOM.render()`, то увидите изменения в пользовательском интерфейсе. Ничего сложного в отслеживании изменений и обновлении интерфейса нет. Благодаря **одностороннему потоку данных** (или *односторонней привязке*), React выполняет данный процесс связанно и быстро. -Simply refer to the [React docs](/docs/) if you need help executing this step. +Если у вас остались вопросы по поводу исполнения данного шага, обратитесь к [React документации](/docs/). -### A Brief Interlude: Props vs State {#a-brief-interlude-props-vs-state} +### Небольшое отступление: пропсы vs состояние {#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: пропсы и состояние. Важно, чтобы вы понимали разницу между ними, в противном случае обратитесь к [официальной React документации](/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} +## Шаг 3: Определяем минимальное (но полноценное) отображение состояния интерфейса {#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**. +Чтобы сделать ваш UI интерактивным, вы должны внести изменения в базовую модель данных. В React это возможно с помощью **состояния**. -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. +Чтобы правильно построить приложение, сначала нужно продумать минимальный набор данных изменяемого состояния, которые требуются вашему приложению. Главное тут следовать принципу разработки [DRY: *Don't Repeat Yourself* (рус. не повторяйся)](https://ru.wikipedia.org/wiki/Don%E2%80%99t_repeat_yourself). Определите минимальное количество необходимого состояния, которое нужно вашему приложению, все остальное вычисляйте при необходимости. Например, если вы создаете список дел, держите массив пунктов списка под рукой; отдельное состояние для перечисления вам не нужно. Вместо этого, чтобы отобразить список, используйте длину массива. -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: +Давайте рассмотрим каждую часть данных и определим, какая из них является состоянием. Задайте себе следующие три вопроса: - 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. Передается ли она от родителя через пропсы? Если это так, вероятно, это не состояние. + 2. Остается ли она неизменной со временем? Если это так, вероятно, это не состояние. + 3. Можете ли вы вычислить ее на основании любой другой части состояния или пропсах в своем компоненте? Если это так, это не состояние. -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. +Исходный список товаров передается через пропсы, так что состоянием он быть не может. Поисковый запрос и чекбокс меняются со временем и не могут быть вычислены, так что они вполне сойдут за состояние. Напоследок, отфильтрованный список товаров не является состоянием, так как его можно вычислить методом совмещения оригинального списка, поискового запроса и значения чекбокса. -So finally, our state is: +В итоге, состоянием являются: - * 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} +## Шаг 4: Определяем, где должно находиться наше состояние{#step-4-identify-where-your-state-should-live} -

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

+

Пример кода Мыслить в React: Шаг 4 на 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. +Итак, мы определили минимальный набор состояний приложения. Далее нам нужно выяснить, какой из компонентов *владеет* состоянием или изменяет его. -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: +Помните: в React поток данных односторонний и сходит сверху вниз в иерархическом порядке. Изначально не совсем ясно, какой из компонентов каким состоянием должен владеть. **Зачастую это самая сложная часть для новичков.** Следуйте дальнейшим инструкциям, чтобы разобраться что и как: -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 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` 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` + * Задача `ProductTable` отфильтровать список товаров основываясь на состоянии, а `SearchBar` должен отображать состояние для поискового запроса и чекбокса. + * Общий главенствующий компонент для обоих — `FilterableProductTable`. + * С концептуальной точки зрения, имеет смысл содержать текст фильтра и значение чекбокса в `FilterableProductTable`. -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`. +Итак, мы приняли решение расположить наше состояние в `FilterableProductTable`. Первое, что нужно сделать — добавить свойство `this.state = {filterText: '', inStockOnly: false}` в конструктор `FilterableProductTable`, чтобы отобразить начальное состояние нашего приложения. После этого передайте `filterText` и `inStockOnly` в `ProductTable` и `SearchBar` через пропсы. Напоследок, используйте пропсы для фильтрации строк в `ProductTable` и определения значений полей формы `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. +Вы заметите изменения в поведении вашего приложения: задайте значение `"ball"` для `filterText` и обновите страницу. Вы увидите соответствующие изменения в таблице данных. -## Step 5: Add Inverse Data Flow {#step-5-add-inverse-data-flow} +## Шаг 5: Добавляем обратный поток данных {#step-5-add-inverse-data-flow} -

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

+

Пример кода Мыслить в React: Шаг 5 на 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`. +До этого момента мы создавали приложение, отображающее функцию пропсов и состояния снисходящих по иерархии. Теперь пришло время обеспечить поток данных в обратную сторону: наша задача сделать так, чтобы компоненты формы в самом низу иерархии обновляли состояние в `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 — прямой, что помогает лучше понять работу приложения, но в связи с этим нам потребуется немного больше кода, чем в традиционной двусторонней привязке данных. -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 попросту игнорирует любой ввод. Это преднамеренно, так как ранее мы приравняли значение пропа `value` в `input` к `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. +Подумайте, какая задача стоит перед нами теперь. Нам нужно, чтобы при изменениях поисковой формы, менялось и состояние ввода. Так как компоненты должны обновлять только относящееся к ним состояние, `FilterableProductTable` будет передавать колбэки в `SearchBar`, который будет срабатывать при каждом обновлении состояния. Чтобы получать уведомления об изменениях элементов формы, мы можем использовать событие `onChange`. Колбэки, переданные через компонент `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. Хотя этот процесс и использует немного больше кода, помните, код читают чаще, чем пишут. А такой модульный и прямой код, как в нашем приложении, читается очень легко. Когда вы начнете создавать большие библиотеки компонентов, вы сможете по-настоящему оценить прямолинейность и связанность React, а повторно используемые компоненты сделают ваш код намного меньше. :) From d754c7e266fa5039f58ba67649236f6147104d85 Mon Sep 17 00:00:00 2001 From: "Marichka (Tsiuriak) Offen" <40467112+marichka-offen@users.noreply.github.com> Date: Mon, 11 Feb 2019 15:44:48 -0500 Subject: [PATCH 02/13] Update title thinking-in-react.md --- content/docs/thinking-in-react.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/thinking-in-react.md b/content/docs/thinking-in-react.md index 1dc7f7150..5de97da27 100644 --- a/content/docs/thinking-in-react.md +++ b/content/docs/thinking-in-react.md @@ -1,6 +1,6 @@ --- id: thinking-in-react -title: Мыслить в React +title: Философия React permalink: docs/thinking-in-react.html redirect_from: - 'blog/2013/11/05/thinking-in-react.html' From 95fd56c50d918a37a9b48d758bc6a3234c291cf0 Mon Sep 17 00:00:00 2001 From: "Marichka (Tsiuriak) Offen" <40467112+marichka-offen@users.noreply.github.com> Date: Tue, 12 Feb 2019 09:40:17 -0500 Subject: [PATCH 03/13] Implement recommended changes --- content/docs/thinking-in-react.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/content/docs/thinking-in-react.md b/content/docs/thinking-in-react.md index 5de97da27..51ae457f4 100644 --- a/content/docs/thinking-in-react.md +++ b/content/docs/thinking-in-react.md @@ -8,17 +8,17 @@ redirect_from: prev: composition-vs-inheritance.html --- -По нашему мнению, React является ведущей технологией в построении больших, быстрых веб-приложений на основе JavaScript. Показателем этого есть успешная работа Facebook и Instagram. +По нашему мнению, React лучший способ создания больших и быстрых веб-приложений на основе JavaScript. Он очень хорошо масштабировался для нас в Facebook и Instagram. -Одним из главных вкладов React есть то, что он помогает лучше осмыслить приложение в процессе его написания. На данной странице мы рассмотрим необходимый ход мысли на примере создания инвентарной таблицы с функцией поиска. +Одна из особенностей React — это то, как он предлагает думать о приложениях в процессе их создании. В этом руководстве мы познакомим вас с процессом как создать таблицу учета продуктов с возможностью поиска в React. -## Взглянем на макет {#start-with-a-mock} +## Начнем с макета {#start-with-a-mock} Представьте, что у вас уже есть JSON API и макет дизайна сайта. Вот как он выглядит: ![Mockup](../images/blog/thinking-in-react-mock.png) -Наш JSON API возвращает вот такие вот данные: +Наш JSON API возвращает данные, которые выглядят так: ``` [ @@ -31,11 +31,11 @@ prev: composition-vs-inheritance.html ]; ``` -## Шаг 1: Разбиваем пользовательский интерфейс на составляющие{#step-1-break-the-ui-into-a-component-hierarchy} +## Шаг 1: Разбить пользовательский интерфейс на составляющие{#step-1-break-the-ui-into-a-component-hierarchy} -Первое, что нужно сделать — очертить границы вокруг каждого компонента (и подкомпонента) в макете и дать им имена. Если вы работаете в паре с дизайнером, вполне возможно, что он уже сделал это за вас. Так, слои в Photoshop отлично подходят для наименования React-компонентов. +Первое, что нужно сделать — представить границы вокруг каждого компонента (и подкомпонента) в макете и дать им имена. Если вы работаете в паре с дизайнером, вполне возможно, что он уже сделал это за вас. Так, слои в Photoshop отлично подходят для наименования React-компонентов. -Но как узнать, что является компонентом, а что нет? Все очень просто: задействуйте тот же метод, который используете при определении новой функции или объекта. Одним из таких методов есть [принцип единственной ответственности](https://ru.wikipedia.org/wiki/Принцип_единственной_ответственности), суть которого состоит в том, что в идеале компонент должен выполнять только одну поставленную задачу. Если в конечном итоге функционал компонента увеличивается, его следует разбить на более мелкие подкомпоненты. +Но как узнать, что является компонентом, а что нет? Все очень просто: задействуйте тот же метод, который используете при определении новой функции или объекта. Один из таких методов — [принцип единственной ответственности](https://ru.wikipedia.org/wiki/Принцип_единственной_ответственности), суть которого состоит в том, что в идеале компонент должен выполнять только одну поставленную задачу. Если в конечном итоге функционал компонента увеличивается, его следует разбить на более мелкие подкомпоненты. Поскольку мы часто показываем модель данных JSON пользователю, вы обнаружите, что если ваша модель была построена правильно, то пользовательский интерфейс (а следовательно и структура компонентов) отобразятся надлежащим образом. Это связано с тем, что UI и модели данных имеют свойство соблюдать аналогичную *информационную архитектуру*, а это в свою очередь значит, что разделять интерфейс на составляющие не имеет смысла. Просто разбейте его на компоненты, которые будут отображать одну конкретную модель данных. @@ -51,7 +51,7 @@ prev: composition-vs-inheritance.html При взгляде на компонент `ProductTable` несложно заметить, что заголовок таблицы ("Name" и "Price") сам по себе отдельным компонентом не является. Отделять его или нет — вопрос личного предпочтения, существует ряд аргументов как за, так и против. В данном примере мы решили не придавать этому особого значения и оставить заголовок частью большего компонента `ProductTable`, так как он является всего лишь малой частью общего *сбора данных*. Тем не менее, если в будущем заголовок пополнится новыми функциями (например, возможностью сортировать товар), имеет смысл отделить его в самостоятельный компонент `ProductTableHeader`. -Тепер, когда мы определили компоненты в нашем макете, давайте расположим их по порядку подчиненности. Это просто. Компоненты, которые являются частью других компонентов, в иерархии отображаются как дочерние: +Теперь, когда мы определили компоненты в нашем макете, давайте расположим их по порядку подчиненности. Это просто. Компоненты, которые являются частью других компонентов, в иерархии отображаются как дочерние: * `FilterableProductTable` * `SearchBar` @@ -61,7 +61,7 @@ prev: composition-vs-inheritance.html ## Шаг 2: Создаем статическую версию в React {#step-2-build-a-static-version-in-react} -

Пример кода Мыслить в React: Шаг 2 на CodePen.

+

Пример кода Философия React: Шаг 2 на CodePen.

Теперь, когда все компоненты расположены в иерархическом порядке, самое время реализовать наше приложение. Самый легкий способ — создать версию, которая использует модель данных и отрисовывает интерфейс, но не предполагает никакой интерактивности. Разделение этих процессов считается лучшей практикой, поскольку написание статической версии требует много печатания и совсем немного мышления, в то время как создание интерактивности приложения подразумевает более глубокий мыслительный процесс и лишь долю рутинной печати. Рассмотрим почему. @@ -106,7 +106,7 @@ prev: composition-vs-inheritance.html ## Шаг 4: Определяем, где должно находиться наше состояние{#step-4-identify-where-your-state-should-live} -

Пример кода Мыслить в React: Шаг 4 на CodePen.

+

Пример кода Философия React: Шаг 4 на CodePen.

Итак, мы определили минимальный набор состояний приложения. Далее нам нужно выяснить, какой из компонентов *владеет* состоянием или изменяет его. @@ -131,7 +131,7 @@ prev: composition-vs-inheritance.html ## Шаг 5: Добавляем обратный поток данных {#step-5-add-inverse-data-flow} -

Пример кода Мыслить в React: Шаг 5 на CodePen.

+

Пример кода Философия React: Шаг 5 на CodePen.

До этого момента мы создавали приложение, отображающее функцию пропсов и состояния снисходящих по иерархии. Теперь пришло время обеспечить поток данных в обратную сторону: наша задача сделать так, чтобы компоненты формы в самом низу иерархии обновляли состояние в `FilterableProductTable`. From f5bb349767ad2dd4ed5bc16bdf90c2243a0590d8 Mon Sep 17 00:00:00 2001 From: "Marichka (Tsiuriak) Offen" <40467112+marichka-offen@users.noreply.github.com> Date: Tue, 12 Feb 2019 09:44:21 -0500 Subject: [PATCH 04/13] Fix steps headers --- content/docs/thinking-in-react.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/content/docs/thinking-in-react.md b/content/docs/thinking-in-react.md index 51ae457f4..0961d7f87 100644 --- a/content/docs/thinking-in-react.md +++ b/content/docs/thinking-in-react.md @@ -59,7 +59,7 @@ prev: composition-vs-inheritance.html * `ProductCategoryRow` * `ProductRow` -## Шаг 2: Создаем статическую версию в React {#step-2-build-a-static-version-in-react} +## Шаг 2: Создать статическую версию в React {#step-2-build-a-static-version-in-react}

Пример кода Философия React: Шаг 2 на CodePen.

@@ -78,7 +78,7 @@ prev: composition-vs-inheritance.html Существует два типа "модельных" данных в React: пропсы и состояние. Важно, чтобы вы понимали разницу между ними, в противном случае обратитесь к [официальной React документации](/docs/interactivity-and-dynamic-uis.html). -## Шаг 3: Определяем минимальное (но полноценное) отображение состояния интерфейса {#step-3-identify-the-minimal-but-complete-representation-of-ui-state} +## Шаг 3: Определить минимальное (но полноценное) отображение состояния интерфейса {#step-3-identify-the-minimal-but-complete-representation-of-ui-state} Чтобы сделать ваш UI интерактивным, вы должны внести изменения в базовую модель данных. В React это возможно с помощью **состояния**. @@ -104,7 +104,7 @@ prev: composition-vs-inheritance.html * Поисковый запрос, введенный пользователем * Значение чекбокса -## Шаг 4: Определяем, где должно находиться наше состояние{#step-4-identify-where-your-state-should-live} +## Шаг 4: Определить, где должно находиться наше состояние{#step-4-identify-where-your-state-should-live}

Пример кода Философия React: Шаг 4 на CodePen.

@@ -129,7 +129,7 @@ prev: composition-vs-inheritance.html Вы заметите изменения в поведении вашего приложения: задайте значение `"ball"` для `filterText` и обновите страницу. Вы увидите соответствующие изменения в таблице данных. -## Шаг 5: Добавляем обратный поток данных {#step-5-add-inverse-data-flow} +## Шаг 5: Добавить обратный поток данных {#step-5-add-inverse-data-flow}

Пример кода Философия React: Шаг 5 на CodePen.

From 75a9ce73010634b816d04917b3d55aa91dbbd9a1 Mon Sep 17 00:00:00 2001 From: "Marichka (Tsiuriak) Offen" <40467112+marichka-offen@users.noreply.github.com> Date: Tue, 12 Feb 2019 10:04:04 -0500 Subject: [PATCH 05/13] Fix typo --- content/docs/thinking-in-react.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/docs/thinking-in-react.md b/content/docs/thinking-in-react.md index 0961d7f87..2f8076104 100644 --- a/content/docs/thinking-in-react.md +++ b/content/docs/thinking-in-react.md @@ -10,7 +10,7 @@ prev: composition-vs-inheritance.html По нашему мнению, React лучший способ создания больших и быстрых веб-приложений на основе JavaScript. Он очень хорошо масштабировался для нас в Facebook и Instagram. -Одна из особенностей React — это то, как он предлагает думать о приложениях в процессе их создании. В этом руководстве мы познакомим вас с процессом как создать таблицу учета продуктов с возможностью поиска в React. +Одна из особенностей React — это то, как он предлагает думать о приложениях в процессе их создания. В этом руководстве мы познакомим вас с процессом как создать таблицу учета продуктов с возможностью поиска в React. ## Начнем с макета {#start-with-a-mock} From 7859f034c3f0a4913dff3de65b30b50565f034fb Mon Sep 17 00:00:00 2001 From: "Marichka (Tsiuriak) Offen" <40467112+marichka-offen@users.noreply.github.com> Date: Tue, 12 Feb 2019 15:46:46 -0500 Subject: [PATCH 06/13] Fix thinking in react --- content/docs/thinking-in-react.md | 60 +++++++++++++++---------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/content/docs/thinking-in-react.md b/content/docs/thinking-in-react.md index 2f8076104..990d4ac84 100644 --- a/content/docs/thinking-in-react.md +++ b/content/docs/thinking-in-react.md @@ -8,9 +8,9 @@ redirect_from: prev: composition-vs-inheritance.html --- -По нашему мнению, React лучший способ создания больших и быстрых веб-приложений на основе JavaScript. Он очень хорошо масштабировался для нас в Facebook и Instagram. +По нашему мнению, React — отличный способ создания больших и быстрых веб-приложений на основе JavaScript. Он очень хорошо масштабировался для нас в Facebook и Instagram. -Одна из особенностей React — это то, как он предлагает думать о приложениях в процессе их создания. В этом руководстве мы познакомим вас с процессом как создать таблицу учета продуктов с возможностью поиска в React. +Одна из особенностей React — это то, как он предлагает думать о приложениях в процессе их создания. В этом руководстве мы покажем мысленный процесс создания таблицы продуктов с поиском на React. ## Начнем с макета {#start-with-a-mock} @@ -33,23 +33,23 @@ prev: composition-vs-inheritance.html ## Шаг 1: Разбить пользовательский интерфейс на составляющие{#step-1-break-the-ui-into-a-component-hierarchy} -Первое, что нужно сделать — представить границы вокруг каждого компонента (и подкомпонента) в макете и дать им имена. Если вы работаете в паре с дизайнером, вполне возможно, что он уже сделал это за вас. Так, слои в Photoshop отлично подходят для наименования React-компонентов. +Первое, что нужно сделать — представить границы вокруг каждого компонента (и подкомпонента) в макете и дать им имена. Если вы работаете с дизайнерами, вполне возможно, что они уже как-то называют компоненты — вам стоит пообщаться! Так, слои в Photoshop отлично подходят для наименования React-компонентов. -Но как узнать, что является компонентом, а что нет? Все очень просто: задействуйте тот же метод, который используете при определении новой функции или объекта. Один из таких методов — [принцип единственной ответственности](https://ru.wikipedia.org/wiki/Принцип_единственной_ответственности), суть которого состоит в том, что в идеале компонент должен выполнять только одну поставленную задачу. Если в конечном итоге функционал компонента увеличивается, его следует разбить на более мелкие подкомпоненты. +Но как узнать, что является компонентом, а что нет? Всё очень просто: это похоже на то, как вы решаете, надо ли объявить функцию или объект. Один из таких методов — [принцип единственной ответственности](https://ru.wikipedia.org/wiki/Принцип_единственной_ответственности), суть которого состоит в том, что в идеале компонент должен выполнять только одну поставленную задачу. Если в конечном итоге функционал компонента увеличивается, его следует разбить на более мелкие подкомпоненты. -Поскольку мы часто показываем модель данных JSON пользователю, вы обнаружите, что если ваша модель была построена правильно, то пользовательский интерфейс (а следовательно и структура компонентов) отобразятся надлежащим образом. Это связано с тем, что UI и модели данных имеют свойство соблюдать аналогичную *информационную архитектуру*, а это в свою очередь значит, что разделять интерфейс на составляющие не имеет смысла. Просто разбейте его на компоненты, которые будут отображать одну конкретную модель данных. +Поскольку мы часто показываем модель данных JSON пользователю, вы обнаружите, что если ваша модель была построена правильно, то пользовательский интерфейс (а следовательно и структура компонентов) отобразятся надлежащим образом. Это связано с тем, что UI и модели данных имеют свойство соблюдать аналогичную *информационную архитектуру*, а это в свою очередь значит, что разделять интерфейс на составляющие не составляет труда. Просто разбейте его на компоненты, каждый из которых отображает часть модели данных. ![Component diagram](../images/blog/thinking-in-react-components.png) -Здесь мы видим, что наше простое приложение состоит из пяти различных компонентов. Курсивом выделены данные, которые эти компоненты представляють. +Здесь мы видим, что наше простое приложение состоит из пяти различных компонентов. Курсивом выделены данные, которые эти компоненты представляют. - 1. **`FilterableProductTable` (оранжевый):** контейнер, содержащий компоненты и подкомпоненты примера + 1. **`FilterableProductTable` (оранжевый):** контейнер, содержащий пример целиком 2. **`SearchBar` (синий):** поле *пользовательского ввода* - 3. **`ProductTable` (зелёный):** отображает и фильтрует *сбор данных*, основанный на *пользовательском вводе* + 3. **`ProductTable` (зелёный):** отображает и фильтрует *список данных*, основанный на *пользовательском вводе* 4. **`ProductCategoryRow` (голубой):** наименования *категорий* - 5. **`ProductRow` (красный):** отдельно взятая *единица товара* + 5. **`ProductRow` (красный):** отдельно взятый *товар* -При взгляде на компонент `ProductTable` несложно заметить, что заголовок таблицы ("Name" и "Price") сам по себе отдельным компонентом не является. Отделять его или нет — вопрос личного предпочтения, существует ряд аргументов как за, так и против. В данном примере мы решили не придавать этому особого значения и оставить заголовок частью большего компонента `ProductTable`, так как он является всего лишь малой частью общего *сбора данных*. Тем не менее, если в будущем заголовок пополнится новыми функциями (например, возможностью сортировать товар), имеет смысл отделить его в самостоятельный компонент `ProductTableHeader`. +При взгляде на компонент `ProductTable` несложно заметить, что заголовок таблицы ("Name" и "Price") сам по себе отдельным компонентом не является. Отделять его или нет — вопрос личного предпочтения, существует ряд аргументов как за, так и против. В данном примере мы решили не придавать этому особого значения и оставить заголовок частью большего компонента `ProductTable`, так как он является всего лишь малой частью общего *списка данных*. Тем не менее, если в будущем заголовок пополнится новыми функциями (например, возможностью сортировать товар), имеет смысл отделить его в самостоятельный компонент `ProductTableHeader`. Теперь, когда мы определили компоненты в нашем макете, давайте расположим их по порядку подчиненности. Это просто. Компоненты, которые являются частью других компонентов, в иерархии отображаются как дочерние: @@ -64,40 +64,40 @@ prev: composition-vs-inheritance.html

Пример кода Философия React: Шаг 2 на CodePen.

-Теперь, когда все компоненты расположены в иерархическом порядке, самое время реализовать наше приложение. Самый легкий способ — создать версию, которая использует модель данных и отрисовывает интерфейс, но не предполагает никакой интерактивности. Разделение этих процессов считается лучшей практикой, поскольку написание статической версии требует много печатания и совсем немного мышления, в то время как создание интерактивности приложения подразумевает более глубокий мыслительный процесс и лишь долю рутинной печати. Рассмотрим почему. +Теперь, когда все компоненты расположены в иерархическом порядке, самое время реализовать наше приложение. Самый легкий способ — создать версию, которая использует модель данных и отрисовывает интерфейс, но не предполагает никакой интерактивности. Разделять эти процессы полезно, поскольку написание статической версии требует много печатания и совсем немного мышления, в то время как создание интерактивности приложения подразумевает более глубокий мыслительный процесс и лишь долю рутинной печати. Рассмотрим почему. -Чтобы построить статическую версию приложения, отображающую модель данных, нам нужно создать компоненты, которые используют другие компоненты и передают данные через *пропсы*. *Пропсы* — это способ передачи данных от родителя к потомку. Если вы знакомы с понятием *состояния*, то для статической версии это как раз то, чего вам **использовать не нужно**. Состояние подразумевает собой данные, которые меняются со временем, что и есть интерактивностью. Так как мы работаем над статической версией приложения, нам этого не нужно. +Чтобы построить статическую версию приложения, отображающую модель данных, нам нужно создать компоненты, которые используют другие компоненты и передают данные через *пропсы*. *Пропсы* — это способ передачи данных от родителя к потомку. Если вы знакомы с понятием *состояния*, то для статической версии это как раз то, чего вам **использовать не нужно**. Состояние подразумевает собой данные, которые меняются со временем, то есть интерактивность. Так как мы работаем над статической версией приложения, нам этого не нужно. -Написание кода вы можете начать как с больших компонентов (`FilterableProductTable`), так и с малых подкомпонентов (`ProductRow`). Более простые приложения удобнее начать с компонентов, находящихся выше по иерархии, в более сложных приложениях лучшей практикой в первую очередь считается создание и тестирование подкомпонентов. +Написание кода вы можете начать как с больших компонентов (`FilterableProductTable`), так и с малых подкомпонентов (`ProductRow`). Более простые приложения удобнее начать с компонентов, находящихся выше по иерархии, в более сложных приложениях удобнее в первую очередь создавать и тестирование подкомпоненты. В конце этого шага у вас на руках должна быть библиотека повторно используемых компонентов, которые отображают вашу модель данных. Так как это статическая версия, компоненты будут иметь только `render()` методы. Компонент выше по иерархии (`FilterableProductTable`) будет передавать модель данных через пропсы. Если вы внесете изменения в базовую модель данных и снова вызовете `ReactDOM.render()`, то увидите изменения в пользовательском интерфейсе. Ничего сложного в отслеживании изменений и обновлении интерфейса нет. Благодаря **одностороннему потоку данных** (или *односторонней привязке*), React выполняет данный процесс связанно и быстро. -Если у вас остались вопросы по поводу исполнения данного шага, обратитесь к [React документации](/docs/). +Если у вас остались вопросы по поводу исполнения данного шага, обратитесь к [документации React](/docs/). ### Небольшое отступление: пропсы vs состояние {#a-brief-interlude-props-vs-state} -Существует два типа "модельных" данных в React: пропсы и состояние. Важно, чтобы вы понимали разницу между ними, в противном случае обратитесь к [официальной React документации](/docs/interactivity-and-dynamic-uis.html). +Существует два типа "модели" данных в React: пропсы и состояние. Важно, чтобы вы понимали разницу между ними, в противном случае обратитесь к [официальной React документации](/docs/interactivity-and-dynamic-uis.html). ## Шаг 3: Определить минимальное (но полноценное) отображение состояния интерфейса {#step-3-identify-the-minimal-but-complete-representation-of-ui-state} Чтобы сделать ваш UI интерактивным, вы должны внести изменения в базовую модель данных. В React это возможно с помощью **состояния**. -Чтобы правильно построить приложение, сначала нужно продумать минимальный набор данных изменяемого состояния, которые требуются вашему приложению. Главное тут следовать принципу разработки [DRY: *Don't Repeat Yourself* (рус. не повторяйся)](https://ru.wikipedia.org/wiki/Don%E2%80%99t_repeat_yourself). Определите минимальное количество необходимого состояния, которое нужно вашему приложению, все остальное вычисляйте при необходимости. Например, если вы создаете список дел, держите массив пунктов списка под рукой; отдельное состояние для перечисления вам не нужно. Вместо этого, чтобы отобразить список, используйте длину массива. +Чтобы правильно построить приложение, сначала нужно продумать минимальный набор данных изменяемого состояния, которые требуются вашему приложению. Главное тут следовать принципу разработки [DRY: *Don't Repeat Yourself* (рус. не повторяйся)](https://ru.wikipedia.org/wiki/Don%E2%80%99t_repeat_yourself). Определите минимальное количество необходимого состояния, которое нужно вашему приложению, всё остальное вычисляйте при необходимости. Например, если вы создаете список дел, держите массив пунктов списка под рукой; отдельное состояние для перечисления вам не нужно. Если надо отобразить количество элементов в списке, просто используйте длину существующего массива. -Задумайтесь обо всех частях данных в нашем приложении. У нас есть: +Давайте перечислим все данные в нашем приложении. У нас есть: * Первоначальный список товаров. - * Поисковый запрос, введенный пользователем. + * Поисковый запрос, введённый пользователем. * Значение чекбокса. * Отфильтрованный список товаров. Давайте рассмотрим каждую часть данных и определим, какая из них является состоянием. Задайте себе следующие три вопроса: - 1. Передается ли она от родителя через пропсы? Если это так, вероятно, это не состояние. + 1. Передаётся ли она от родителя через пропсы? Если это так, вероятно, это не состояние. 2. Остается ли она неизменной со временем? Если это так, вероятно, это не состояние. - 3. Можете ли вы вычислить ее на основании любой другой части состояния или пропсах в своем компоненте? Если это так, это не состояние. + 3. Можете ли вы вычислить её на основании любой другой части состояния или пропсах в своём компоненте? Если это так, это не состояние. -Исходный список товаров передается через пропсы, так что состоянием он быть не может. Поисковый запрос и чекбокс меняются со временем и не могут быть вычислены, так что они вполне сойдут за состояние. Напоследок, отфильтрованный список товаров не является состоянием, так как его можно вычислить методом совмещения оригинального списка, поискового запроса и значения чекбокса. +Исходный список товаров передаётся через пропсы, так что состоянием он быть не может. Поисковый запрос и чекбокс меняются со временем и не могут быть вычислены, так что они вполне сойдут за состояние. Напоследок, отфильтрованный список товаров не является состоянием, так как его можно вычислить методом совмещения оригинального списка, поискового запроса и значения чекбокса. В итоге, состоянием являются: @@ -110,20 +110,20 @@ prev: composition-vs-inheritance.html Итак, мы определили минимальный набор состояний приложения. Далее нам нужно выяснить, какой из компонентов *владеет* состоянием или изменяет его. -Помните: в React поток данных односторонний и сходит сверху вниз в иерархическом порядке. Изначально не совсем ясно, какой из компонентов каким состоянием должен владеть. **Зачастую это самая сложная часть для новичков.** Следуйте дальнейшим инструкциям, чтобы разобраться что и как: +Помните: в React поток данных односторонний и сходит сверху вниз в иерархическом порядке. Изначально не совсем ясно, какой из компонентов должен владеть каким состоянием. **Зачастую это самая сложная часть для новичков.** Чтобы разобраться, следуйте этим инструкциям: Для каждой части состояния в приложении: - * Определите компоненты, которые отражают что-то исходя из состояния. - * Найдите общий главенствующий компонент (компонент расположенный над другими компонентами, нуждающимися в задействовании состояния). - * Либо общий главенствующий компонент, либо любой компонент стоящий выше по иерархии должен содержать состояние. - * Если вам не удается найти подходящий компонент, создайте один исключительно для состояния и разместите его выше по иерархии над общим главенствующим компонентом. + * Определите компоненты, которые рендерят что-то исходя из состояния. + * Найдите общий главенствующий компонент (компонент расположенный над другими компонентами, которым нужно это состояние). + * Либо общий главенствующий компонент, либо любой компонент, стоящий выше по иерархии, должен содержать состояние. + * Если вам не удаётся найти подходящий компонент, создайте один исключительно для состояния и разместите его выше по иерархии над общим главенствующим компонентом. -Давайте рассмотрим эту стратегию на примере нашего приложения: +Давайте применим эту стратегию на примере нашего приложения: - * Задача `ProductTable` отфильтровать список товаров основываясь на состоянии, а `SearchBar` должен отображать состояние для поискового запроса и чекбокса. + * Задача `ProductTable` — отфильтровать список товаров, основываясь на состоянии, а `SearchBar` должен отображать состояние для поискового запроса и чекбокса. * Общий главенствующий компонент для обоих — `FilterableProductTable`. - * С концептуальной точки зрения, имеет смысл содержать текст фильтра и значение чекбокса в `FilterableProductTable`. + * По идее, имеет смысл содержать текст фильтра и значение чекбокса в `FilterableProductTable`. Итак, мы приняли решение расположить наше состояние в `FilterableProductTable`. Первое, что нужно сделать — добавить свойство `this.state = {filterText: '', inStockOnly: false}` в конструктор `FilterableProductTable`, чтобы отобразить начальное состояние нашего приложения. После этого передайте `filterText` и `inStockOnly` в `ProductTable` и `SearchBar` через пропсы. Напоследок, используйте пропсы для фильтрации строк в `ProductTable` и определения значений полей формы `SearchBar`. @@ -137,7 +137,7 @@ prev: composition-vs-inheritance.html Поток данных в React — прямой, что помогает лучше понять работу приложения, но в связи с этим нам потребуется немного больше кода, чем в традиционной двусторонней привязке данных. -Если вы попытаетесь ввести текст в поисковике или установить флажок в чекбоксе данной версии примера, то увидите, что React попросту игнорирует любой ввод. Это преднамеренно, так как ранее мы приравняли значение пропа `value` в `input` к `state (состоянию)` в `FilterableProductTable`. +Если вы попытаетесь ввести текст в поисковике или установить флажок в чекбоксе данной версии примера, то увидите, что React попросту игнорирует любой ввод. Это преднамеренно, так как ранее мы приравняли значение пропа `value` в `input` к `state` в `FilterableProductTable`. Подумайте, какая задача стоит перед нами теперь. Нам нужно, чтобы при изменениях поисковой формы, менялось и состояние ввода. Так как компоненты должны обновлять только относящееся к ним состояние, `FilterableProductTable` будет передавать колбэки в `SearchBar`, который будет срабатывать при каждом обновлении состояния. Чтобы получать уведомления об изменениях элементов формы, мы можем использовать событие `onChange`. Колбэки, переданные через компонент `FilterableProductTable`, вызовут `setState()`, и приложение обновится. From 9b5446f6831095e730bef6092be00c2f5901f669 Mon Sep 17 00:00:00 2001 From: "Marichka (Tsiuriak) Offen" <40467112+marichka-offen@users.noreply.github.com> Date: Tue, 12 Feb 2019 16:16:14 -0500 Subject: [PATCH 07/13] Update steps headers --- content/docs/thinking-in-react.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/content/docs/thinking-in-react.md b/content/docs/thinking-in-react.md index 990d4ac84..e17dfb15d 100644 --- a/content/docs/thinking-in-react.md +++ b/content/docs/thinking-in-react.md @@ -31,7 +31,7 @@ prev: composition-vs-inheritance.html ]; ``` -## Шаг 1: Разбить пользовательский интерфейс на составляющие{#step-1-break-the-ui-into-a-component-hierarchy} +## Шаг 1: Разобьём интерфейс на составляющие {#step-1-break-the-ui-into-a-component-hierarchy} Первое, что нужно сделать — представить границы вокруг каждого компонента (и подкомпонента) в макете и дать им имена. Если вы работаете с дизайнерами, вполне возможно, что они уже как-то называют компоненты — вам стоит пообщаться! Так, слои в Photoshop отлично подходят для наименования React-компонентов. @@ -59,7 +59,7 @@ prev: composition-vs-inheritance.html * `ProductCategoryRow` * `ProductRow` -## Шаг 2: Создать статическую версию в React {#step-2-build-a-static-version-in-react} +## Шаг 2: Создадим статическую версию в React {#step-2-build-a-static-version-in-react}

Пример кода Философия React: Шаг 2 на CodePen.

@@ -78,7 +78,7 @@ prev: composition-vs-inheritance.html Существует два типа "модели" данных в React: пропсы и состояние. Важно, чтобы вы понимали разницу между ними, в противном случае обратитесь к [официальной React документации](/docs/interactivity-and-dynamic-uis.html). -## Шаг 3: Определить минимальное (но полноценное) отображение состояния интерфейса {#step-3-identify-the-minimal-but-complete-representation-of-ui-state} +## Шаг 3: Определим минимальное (но полноценное) отображение состояния интерфейса {#step-3-identify-the-minimal-but-complete-representation-of-ui-state} Чтобы сделать ваш UI интерактивным, вы должны внести изменения в базовую модель данных. В React это возможно с помощью **состояния**. @@ -104,7 +104,7 @@ prev: composition-vs-inheritance.html * Поисковый запрос, введенный пользователем * Значение чекбокса -## Шаг 4: Определить, где должно находиться наше состояние{#step-4-identify-where-your-state-should-live} +## Шаг 4: Определим, где должно находиться наше состояние{#step-4-identify-where-your-state-should-live}

Пример кода Философия React: Шаг 4 на CodePen.

@@ -129,7 +129,7 @@ prev: composition-vs-inheritance.html Вы заметите изменения в поведении вашего приложения: задайте значение `"ball"` для `filterText` и обновите страницу. Вы увидите соответствующие изменения в таблице данных. -## Шаг 5: Добавить обратный поток данных {#step-5-add-inverse-data-flow} +## Шаг 5: Добавим обратный поток данных {#step-5-add-inverse-data-flow}

Пример кода Философия React: Шаг 5 на CodePen.

From e5e95a071da833e2342828a2585bac395ddd6d63 Mon Sep 17 00:00:00 2001 From: "Marichka (Tsiuriak) Offen" <40467112+marichka-offen@users.noreply.github.com> Date: Tue, 12 Feb 2019 17:24:17 -0500 Subject: [PATCH 08/13] Work on big sentences --- content/docs/thinking-in-react.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/content/docs/thinking-in-react.md b/content/docs/thinking-in-react.md index e17dfb15d..2c87f3fa7 100644 --- a/content/docs/thinking-in-react.md +++ b/content/docs/thinking-in-react.md @@ -35,9 +35,9 @@ prev: composition-vs-inheritance.html Первое, что нужно сделать — представить границы вокруг каждого компонента (и подкомпонента) в макете и дать им имена. Если вы работаете с дизайнерами, вполне возможно, что они уже как-то называют компоненты — вам стоит пообщаться! Так, слои в Photoshop отлично подходят для наименования React-компонентов. -Но как узнать, что является компонентом, а что нет? Всё очень просто: это похоже на то, как вы решаете, надо ли объявить функцию или объект. Один из таких методов — [принцип единственной ответственности](https://ru.wikipedia.org/wiki/Принцип_единственной_ответственности), суть которого состоит в том, что в идеале компонент должен выполнять только одну поставленную задачу. Если в конечном итоге функционал компонента увеличивается, его следует разбить на более мелкие подкомпоненты. +Но как узнать, что является компонентом, а что нет? Всё очень просто: это похоже на то, как вы решаете, надо ли объявить функцию или объект. Можно применить [принцип единственной ответственности](https://ru.wikipedia.org/wiki/Принцип_единственной_ответственности): каждый компонент по-хорошему должен заниматься какой-то одной задачей. Если в конечном итоге функционал компонента увеличивается, его следует разбить на более мелкие подкомпоненты. -Поскольку мы часто показываем модель данных JSON пользователю, вы обнаружите, что если ваша модель была построена правильно, то пользовательский интерфейс (а следовательно и структура компонентов) отобразятся надлежащим образом. Это связано с тем, что UI и модели данных имеют свойство соблюдать аналогичную *информационную архитектуру*, а это в свою очередь значит, что разделять интерфейс на составляющие не составляет труда. Просто разбейте его на компоненты, каждый из которых отображает часть модели данных. +Поскольку мы часто показываем модель данных JSON пользователю, вы обнаружите, что если ваша модель была построена правильно, то пользовательский интерфейс (а следовательно и структура компонентов) отобразятся надлежащим образом. Это связано с тем, что UI и модели данных имеют свойство соблюдать аналогичную *информационную архитектуру*, что значит — разделить интерфейс на составляющие не составит труда. Просто разбейте его на компоненты, каждый из которых отображает часть модели данных. ![Component diagram](../images/blog/thinking-in-react-components.png) @@ -49,7 +49,7 @@ prev: composition-vs-inheritance.html 4. **`ProductCategoryRow` (голубой):** наименования *категорий* 5. **`ProductRow` (красный):** отдельно взятый *товар* -При взгляде на компонент `ProductTable` несложно заметить, что заголовок таблицы ("Name" и "Price") сам по себе отдельным компонентом не является. Отделять его или нет — вопрос личного предпочтения, существует ряд аргументов как за, так и против. В данном примере мы решили не придавать этому особого значения и оставить заголовок частью большего компонента `ProductTable`, так как он является всего лишь малой частью общего *списка данных*. Тем не менее, если в будущем заголовок пополнится новыми функциями (например, возможностью сортировать товар), имеет смысл отделить его в самостоятельный компонент `ProductTableHeader`. +При взгляде на компонент `ProductTable` несложно заметить, что заголовок таблицы ("Name" и "Price") сам по себе отдельным компонентом не является. Отделять его или нет — вопрос личного предпочтения. В данном примере мы решили не придавать этому особого значения и оставить заголовок частью большего компонента `ProductTable`, так как он является всего лишь малой частью общего *списка данных*. Тем не менее, если в будущем заголовок пополнится новыми функциями (например, возможностью сортировать товар), имеет смысл отделить его в самостоятельный компонент `ProductTableHeader`. Теперь, когда мы определили компоненты в нашем макете, давайте расположим их по порядку подчиненности. Это просто. Компоненты, которые являются частью других компонентов, в иерархии отображаются как дочерние: @@ -66,11 +66,11 @@ prev: composition-vs-inheritance.html Теперь, когда все компоненты расположены в иерархическом порядке, самое время реализовать наше приложение. Самый легкий способ — создать версию, которая использует модель данных и отрисовывает интерфейс, но не предполагает никакой интерактивности. Разделять эти процессы полезно, поскольку написание статической версии требует много печатания и совсем немного мышления, в то время как создание интерактивности приложения подразумевает более глубокий мыслительный процесс и лишь долю рутинной печати. Рассмотрим почему. -Чтобы построить статическую версию приложения, отображающую модель данных, нам нужно создать компоненты, которые используют другие компоненты и передают данные через *пропсы*. *Пропсы* — это способ передачи данных от родителя к потомку. Если вы знакомы с понятием *состояния*, то для статической версии это как раз то, чего вам **использовать не нужно**. Состояние подразумевает собой данные, которые меняются со временем, то есть интерактивность. Так как мы работаем над статической версией приложения, нам этого не нужно. +Чтобы построить статическую версию приложения, отображающую модель данных, нам нужно создать компоненты, которые используют другие компоненты и передают данные через *пропсы*. *Пропсы* — это способ передачи данных от родителя к потомку. Если вы знакомы с понятием *состояния*, то для статической версии это как раз то, чего вам **использовать не нужно**. Состояние подразумевает собой данные, которые меняются со временем — интерактивность. Так как мы работаем над статической версией приложения, нам этого не нужно. -Написание кода вы можете начать как с больших компонентов (`FilterableProductTable`), так и с малых подкомпонентов (`ProductRow`). Более простые приложения удобнее начать с компонентов, находящихся выше по иерархии, в более сложных приложениях удобнее в первую очередь создавать и тестирование подкомпоненты. +Написание кода вы можете начать как с больших компонентов (`FilterableProductTable`), так и с малых подкомпонентов (`ProductRow`). Более простые приложения удобнее начать с компонентов, находящихся выше по иерархии. В более сложных приложениях удобнее в первую очередь создавать и тестирование подкомпоненты. -В конце этого шага у вас на руках должна быть библиотека повторно используемых компонентов, которые отображают вашу модель данных. Так как это статическая версия, компоненты будут иметь только `render()` методы. Компонент выше по иерархии (`FilterableProductTable`) будет передавать модель данных через пропсы. Если вы внесете изменения в базовую модель данных и снова вызовете `ReactDOM.render()`, то увидите изменения в пользовательском интерфейсе. Ничего сложного в отслеживании изменений и обновлении интерфейса нет. Благодаря **одностороннему потоку данных** (или *односторонней привязке*), React выполняет данный процесс связанно и быстро. +В конце этого шага у вас на руках должна быть библиотека повторно используемых компонентов, которые отображают вашу модель данных. Так как это статическая версия, компоненты будут иметь только `render()` методы. Компонент выше по иерархии (`FilterableProductTable`) будет передавать модель данных через пропсы. Если вы внесете изменения в базовую модель данных и снова вызовете `ReactDOM.render()`, то увидите изменения интерфейса. Ничего сложного в отслеживании изменений и обновлении UI нет. Благодаря **одностороннему потоку данных** (или *односторонней привязке*), React выполняет данный процесс связанно и быстро. Если у вас остались вопросы по поводу исполнения данного шага, обратитесь к [документации React](/docs/). @@ -80,9 +80,9 @@ prev: composition-vs-inheritance.html ## Шаг 3: Определим минимальное (но полноценное) отображение состояния интерфейса {#step-3-identify-the-minimal-but-complete-representation-of-ui-state} -Чтобы сделать ваш UI интерактивным, вы должны внести изменения в базовую модель данных. В React это возможно с помощью **состояния**. +Чтобы сделать наш UI интерактивным, нужно внести изменения в базовую модель данных. В React это возможно с помощью **состояния**. -Чтобы правильно построить приложение, сначала нужно продумать минимальный набор данных изменяемого состояния, которые требуются вашему приложению. Главное тут следовать принципу разработки [DRY: *Don't Repeat Yourself* (рус. не повторяйся)](https://ru.wikipedia.org/wiki/Don%E2%80%99t_repeat_yourself). Определите минимальное количество необходимого состояния, которое нужно вашему приложению, всё остальное вычисляйте при необходимости. Например, если вы создаете список дел, держите массив пунктов списка под рукой; отдельное состояние для перечисления вам не нужно. Если надо отобразить количество элементов в списке, просто используйте длину существующего массива. +Чтобы правильно построить приложение, сначала нужно продумать необходимый набор данных изменяемого состояния. Главное тут следовать принципу разработки [DRY: *Don't Repeat Yourself* (рус. не повторяйся)](https://ru.wikipedia.org/wiki/Don%E2%80%99t_repeat_yourself). Определите минимальное количество необходимого состояния, которое нужно вашему приложению, всё остальное вычисляйте при необходимости. Например, если вы создаете список дел, держите массив пунктов списка под рукой; отдельное состояние для перечисления вам не нужно. Если надо отобразить количество элементов в списке, просто используйте длину существующего массива. Давайте перечислим все данные в нашем приложении. У нас есть: @@ -97,7 +97,7 @@ prev: composition-vs-inheritance.html 2. Остается ли она неизменной со временем? Если это так, вероятно, это не состояние. 3. Можете ли вы вычислить её на основании любой другой части состояния или пропсах в своём компоненте? Если это так, это не состояние. -Исходный список товаров передаётся через пропсы, так что состоянием он быть не может. Поисковый запрос и чекбокс меняются со временем и не могут быть вычислены, так что они вполне сойдут за состояние. Напоследок, отфильтрованный список товаров не является состоянием, так как его можно вычислить методом совмещения оригинального списка, поискового запроса и значения чекбокса. +Исходный список товаров передаётся через пропсы, так что состоянием он быть не может. Поисковый запрос и чекбокс меняются со временем и не могут быть вычислены, так что они вполне сойдут за состояние. Напоследок, отфильтрованный список товаров не является состоянием, его можно вычислить методом совмещения оригинального списка, поискового запроса и значения чекбокса. В итоге, состоянием являются: @@ -121,7 +121,7 @@ prev: composition-vs-inheritance.html Давайте применим эту стратегию на примере нашего приложения: - * Задача `ProductTable` — отфильтровать список товаров, основываясь на состоянии, а `SearchBar` должен отображать состояние для поискового запроса и чекбокса. + * Задача `ProductTable` — отфильтровать список товаров, основываясь на состоянии, а `SearchBar` — отобразить состояние для поискового запроса и чекбокса. * Общий главенствующий компонент для обоих — `FilterableProductTable`. * По идее, имеет смысл содержать текст фильтра и значение чекбокса в `FilterableProductTable`. @@ -133,15 +133,15 @@ prev: composition-vs-inheritance.html

Пример кода Философия React: Шаг 5 на CodePen.

-До этого момента мы создавали приложение, отображающее функцию пропсов и состояния снисходящих по иерархии. Теперь пришло время обеспечить поток данных в обратную сторону: наша задача сделать так, чтобы компоненты формы в самом низу иерархии обновляли состояние в `FilterableProductTable`. +До этого момента мы создавали приложение, в котором функция пропсов и состояние предаются вниз по иерархии. Теперь мы обеспечим поток данных в обратную сторону: наша задача сделать так, чтобы компоненты формы в самом низу иерархии обновляли состояние в `FilterableProductTable`. -Поток данных в React — прямой, что помогает лучше понять работу приложения, но в связи с этим нам потребуется немного больше кода, чем в традиционной двусторонней привязке данных. +Поток данных в React — прямой, но в связи с этим нам потребуется немного больше кода, чем в традиционной двусторонней привязке данных. -Если вы попытаетесь ввести текст в поисковике или установить флажок в чекбоксе данной версии примера, то увидите, что React попросту игнорирует любой ввод. Это преднамеренно, так как ранее мы приравняли значение пропа `value` в `input` к `state` в `FilterableProductTable`. +Если вы попытаетесь ввести текст в поисковике или установить флажок в чекбоксе данной версии примера, то увидите, что React игнорирует любой ввод. Это преднамеренно, так как ранее мы приравняли значение пропа `value` в `input` к `state` в `FilterableProductTable`. -Подумайте, какая задача стоит перед нами теперь. Нам нужно, чтобы при изменениях поисковой формы, менялось и состояние ввода. Так как компоненты должны обновлять только относящееся к ним состояние, `FilterableProductTable` будет передавать колбэки в `SearchBar`, который будет срабатывать при каждом обновлении состояния. Чтобы получать уведомления об изменениях элементов формы, мы можем использовать событие `onChange`. Колбэки, переданные через компонент `FilterableProductTable`, вызовут `setState()`, и приложение обновится. +Подумайте, какая задача стоит перед нами теперь. Нам нужно, чтобы при изменениях поисковой формы, менялось состояние ввода. Так как компоненты должны обновлять только относящееся к ним состояние, `FilterableProductTable` будет передавать колбэки в `SearchBar`, который будет срабатывать при каждом обновлении состояния. Чтобы получать уведомления об изменениях элементов формы, мы можем использовать событие `onChange`. Колбэки, переданные через компонент `FilterableProductTable`, вызовут `setState()`, и приложение обновится. -Хоть и звучит сложно, но занимает это всего несколько строчек кода. А прямой поток данных через приложение от этого не меняется. +Хоть и звучит сложно, но занимает это всего несколько строк кода. А прямой поток данных через приложение от этого не меняется. ## Вот и всё {#and-thats-it} From b5d73da5893d1bc292f3f04ddad465e71396623c Mon Sep 17 00:00:00 2001 From: "Marichka (Tsiuriak) Offen" <40467112+marichka-offen@users.noreply.github.com> Date: Tue, 12 Feb 2019 19:31:45 -0500 Subject: [PATCH 09/13] Fix \ --- content/docs/thinking-in-react.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/content/docs/thinking-in-react.md b/content/docs/thinking-in-react.md index 2c87f3fa7..85d5c2901 100644 --- a/content/docs/thinking-in-react.md +++ b/content/docs/thinking-in-react.md @@ -12,7 +12,7 @@ prev: composition-vs-inheritance.html Одна из особенностей React — это то, как он предлагает думать о приложениях в процессе их создания. В этом руководстве мы покажем мысленный процесс создания таблицы продуктов с поиском на React. -## Начнем с макета {#start-with-a-mock} +## Начнём с макета {#start-with-a-mock} Представьте, что у вас уже есть JSON API и макет дизайна сайта. Вот как он выглядит: @@ -51,7 +51,7 @@ prev: composition-vs-inheritance.html При взгляде на компонент `ProductTable` несложно заметить, что заголовок таблицы ("Name" и "Price") сам по себе отдельным компонентом не является. Отделять его или нет — вопрос личного предпочтения. В данном примере мы решили не придавать этому особого значения и оставить заголовок частью большего компонента `ProductTable`, так как он является всего лишь малой частью общего *списка данных*. Тем не менее, если в будущем заголовок пополнится новыми функциями (например, возможностью сортировать товар), имеет смысл отделить его в самостоятельный компонент `ProductTableHeader`. -Теперь, когда мы определили компоненты в нашем макете, давайте расположим их по порядку подчиненности. Это просто. Компоненты, которые являются частью других компонентов, в иерархии отображаются как дочерние: +Теперь, когда мы определили компоненты в нашем макете, давайте расположим их по порядку подчинённости. Это просто. Компоненты, которые являются частью других компонентов, в иерархии отображаются как дочерние: * `FilterableProductTable` * `SearchBar` @@ -64,13 +64,13 @@ prev: composition-vs-inheritance.html

Пример кода Философия React: Шаг 2 на CodePen.

-Теперь, когда все компоненты расположены в иерархическом порядке, самое время реализовать наше приложение. Самый легкий способ — создать версию, которая использует модель данных и отрисовывает интерфейс, но не предполагает никакой интерактивности. Разделять эти процессы полезно, поскольку написание статической версии требует много печатания и совсем немного мышления, в то время как создание интерактивности приложения подразумевает более глубокий мыслительный процесс и лишь долю рутинной печати. Рассмотрим почему. +Теперь, когда все компоненты расположены в иерархическом порядке, самое время реализовать наше приложение. Самый лёгкий способ — создать версию, которая использует модель данных и отрисовывает интерфейс, но не предполагает никакой интерактивности. Разделять эти процессы полезно, поскольку написание статической версии требует много печатания и совсем немного мышления, в то время как создание интерактивности приложения подразумевает более глубокий мыслительный процесс и лишь долю рутинной печати. Рассмотрим почему. Чтобы построить статическую версию приложения, отображающую модель данных, нам нужно создать компоненты, которые используют другие компоненты и передают данные через *пропсы*. *Пропсы* — это способ передачи данных от родителя к потомку. Если вы знакомы с понятием *состояния*, то для статической версии это как раз то, чего вам **использовать не нужно**. Состояние подразумевает собой данные, которые меняются со временем — интерактивность. Так как мы работаем над статической версией приложения, нам этого не нужно. Написание кода вы можете начать как с больших компонентов (`FilterableProductTable`), так и с малых подкомпонентов (`ProductRow`). Более простые приложения удобнее начать с компонентов, находящихся выше по иерархии. В более сложных приложениях удобнее в первую очередь создавать и тестирование подкомпоненты. -В конце этого шага у вас на руках должна быть библиотека повторно используемых компонентов, которые отображают вашу модель данных. Так как это статическая версия, компоненты будут иметь только `render()` методы. Компонент выше по иерархии (`FilterableProductTable`) будет передавать модель данных через пропсы. Если вы внесете изменения в базовую модель данных и снова вызовете `ReactDOM.render()`, то увидите изменения интерфейса. Ничего сложного в отслеживании изменений и обновлении UI нет. Благодаря **одностороннему потоку данных** (или *односторонней привязке*), React выполняет данный процесс связанно и быстро. +В конце этого шага у вас на руках должна быть библиотека повторно используемых компонентов, которые отображают вашу модель данных. Так как это статическая версия, компоненты будут иметь только `render()` методы. Компонент выше по иерархии (`FilterableProductTable`) будет передавать модель данных через пропсы. Если вы внесёте изменения в базовую модель данных и снова вызовете `ReactDOM.render()`, то увидите изменения интерфейса. Ничего сложного в отслеживании изменений и обновлении UI нет. Благодаря **одностороннему потоку данных** (или *односторонней привязке*), React выполняет данный процесс связанно и быстро. Если у вас остались вопросы по поводу исполнения данного шага, обратитесь к [документации React](/docs/). @@ -82,7 +82,7 @@ prev: composition-vs-inheritance.html Чтобы сделать наш UI интерактивным, нужно внести изменения в базовую модель данных. В React это возможно с помощью **состояния**. -Чтобы правильно построить приложение, сначала нужно продумать необходимый набор данных изменяемого состояния. Главное тут следовать принципу разработки [DRY: *Don't Repeat Yourself* (рус. не повторяйся)](https://ru.wikipedia.org/wiki/Don%E2%80%99t_repeat_yourself). Определите минимальное количество необходимого состояния, которое нужно вашему приложению, всё остальное вычисляйте при необходимости. Например, если вы создаете список дел, держите массив пунктов списка под рукой; отдельное состояние для перечисления вам не нужно. Если надо отобразить количество элементов в списке, просто используйте длину существующего массива. +Чтобы правильно построить приложение, сначала нужно продумать необходимый набор данных изменяемого состояния. Главное тут следовать принципу разработки [DRY: *Don't Repeat Yourself* (рус. не повторяйся)](https://ru.wikipedia.org/wiki/Don%E2%80%99t_repeat_yourself). Определите минимальное количество необходимого состояния, которое нужно вашему приложению, всё остальное вычисляйте при необходимости. Например, если вы создаёте список дел, держите массив пунктов списка под рукой; отдельное состояние для перечисления вам не нужно. Если надо отобразить количество элементов в списке, просто используйте длину существующего массива. Давайте перечислим все данные в нашем приложении. У нас есть: @@ -94,14 +94,14 @@ prev: composition-vs-inheritance.html Давайте рассмотрим каждую часть данных и определим, какая из них является состоянием. Задайте себе следующие три вопроса: 1. Передаётся ли она от родителя через пропсы? Если это так, вероятно, это не состояние. - 2. Остается ли она неизменной со временем? Если это так, вероятно, это не состояние. + 2. Остаётся ли она неизменной со временем? Если это так, вероятно, это не состояние. 3. Можете ли вы вычислить её на основании любой другой части состояния или пропсах в своём компоненте? Если это так, это не состояние. Исходный список товаров передаётся через пропсы, так что состоянием он быть не может. Поисковый запрос и чекбокс меняются со временем и не могут быть вычислены, так что они вполне сойдут за состояние. Напоследок, отфильтрованный список товаров не является состоянием, его можно вычислить методом совмещения оригинального списка, поискового запроса и значения чекбокса. В итоге, состоянием являются: - * Поисковый запрос, введенный пользователем + * Поисковый запрос, введённый пользователем * Значение чекбокса ## Шаг 4: Определим, где должно находиться наше состояние{#step-4-identify-where-your-state-should-live} @@ -145,4 +145,4 @@ prev: composition-vs-inheritance.html ## Вот и всё {#and-thats-it} -Надеемся, что данная информация поможет вам получить лучшее представление о том, как подойти к созданию компонентов и приложений в React. Хотя этот процесс и использует немного больше кода, помните, код читают чаще, чем пишут. А такой модульный и прямой код, как в нашем приложении, читается очень легко. Когда вы начнете создавать большие библиотеки компонентов, вы сможете по-настоящему оценить прямолинейность и связанность React, а повторно используемые компоненты сделают ваш код намного меньше. :) +Надеемся, что данная информация поможет вам получить лучшее представление о том, как подойти к созданию компонентов и приложений в React. Хотя этот процесс и использует немного больше кода, помните, код читают чаще, чем пишут. А такой модульный и прямой код, как в нашем приложении, читается очень легко. Когда вы начнёте создавать большие библиотеки компонентов, вы сможете по-настоящему оценить прямолинейность и связанность React, а повторно используемые компоненты сделают ваш код намного меньше. :) From 5122d3b1ca6cf77b55b3d3f36f7bd4e48eca2e9b Mon Sep 17 00:00:00 2001 From: Alexey Pyltsyn Date: Tue, 12 Feb 2019 22:27:53 -0500 Subject: [PATCH 10/13] Apply suggestions from code review Co-Authored-By: marichka-offen <40467112+marichka-offen@users.noreply.github.com> --- content/docs/thinking-in-react.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/content/docs/thinking-in-react.md b/content/docs/thinking-in-react.md index 85d5c2901..7fe544fac 100644 --- a/content/docs/thinking-in-react.md +++ b/content/docs/thinking-in-react.md @@ -72,11 +72,11 @@ prev: composition-vs-inheritance.html В конце этого шага у вас на руках должна быть библиотека повторно используемых компонентов, которые отображают вашу модель данных. Так как это статическая версия, компоненты будут иметь только `render()` методы. Компонент выше по иерархии (`FilterableProductTable`) будет передавать модель данных через пропсы. Если вы внесёте изменения в базовую модель данных и снова вызовете `ReactDOM.render()`, то увидите изменения интерфейса. Ничего сложного в отслеживании изменений и обновлении UI нет. Благодаря **одностороннему потоку данных** (или *односторонней привязке*), React выполняет данный процесс связанно и быстро. -Если у вас остались вопросы по поводу исполнения данного шага, обратитесь к [документации React](/docs/). +Если у вас остались вопросы по выполнению данного шага, обратитесь к [документации React](/docs/). -### Небольшое отступление: пропсы vs состояние {#a-brief-interlude-props-vs-state} +### Небольшое отступление: пропсы в сравнении с состоянием {#a-brief-interlude-props-vs-state} -Существует два типа "модели" данных в React: пропсы и состояние. Важно, чтобы вы понимали разницу между ними, в противном случае обратитесь к [официальной React документации](/docs/interactivity-and-dynamic-uis.html). +Существует два типа "модели" данных в React: пропсы и состояние. Важно, чтобы вы понимали разницу между ними, в противном случае обратитесь к [официальной документации React](/docs/interactivity-and-dynamic-uis.html). ## Шаг 3: Определим минимальное (но полноценное) отображение состояния интерфейса {#step-3-identify-the-minimal-but-complete-representation-of-ui-state} @@ -115,7 +115,7 @@ prev: composition-vs-inheritance.html Для каждой части состояния в приложении: * Определите компоненты, которые рендерят что-то исходя из состояния. - * Найдите общий главенствующий компонент (компонент расположенный над другими компонентами, которым нужно это состояние). + * Найдите общий главенствующий компонент (компонент, расположенный над другими компонентами, которым нужно это состояние). * Либо общий главенствующий компонент, либо любой компонент, стоящий выше по иерархии, должен содержать состояние. * Если вам не удаётся найти подходящий компонент, создайте один исключительно для состояния и разместите его выше по иерархии над общим главенствующим компонентом. From 6c846bc513b67dd870fd823e950654c61e5576d2 Mon Sep 17 00:00:00 2001 From: "Marichka (Tsiuriak) Offen" <40467112+marichka-offen@users.noreply.github.com> Date: Tue, 12 Feb 2019 22:42:20 -0500 Subject: [PATCH 11/13] Apply suggestions from code review --- content/docs/thinking-in-react.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/content/docs/thinking-in-react.md b/content/docs/thinking-in-react.md index 7fe544fac..3d743f5ae 100644 --- a/content/docs/thinking-in-react.md +++ b/content/docs/thinking-in-react.md @@ -64,13 +64,13 @@ prev: composition-vs-inheritance.html

Пример кода Философия React: Шаг 2 на CodePen.

-Теперь, когда все компоненты расположены в иерархическом порядке, самое время реализовать наше приложение. Самый лёгкий способ — создать версию, которая использует модель данных и отрисовывает интерфейс, но не предполагает никакой интерактивности. Разделять эти процессы полезно, поскольку написание статической версии требует много печатания и совсем немного мышления, в то время как создание интерактивности приложения подразумевает более глубокий мыслительный процесс и лишь долю рутинной печати. Рассмотрим почему. +Теперь, когда все компоненты расположены в иерархическом порядке, пришло время реализовать наше приложение. Самый легкий способ — создать версию, которая использует модель данных и рендерит интерфейс, но не предполагает никакой интерактивности. Разделять эти процессы полезно, поскольку написание статической версии требует много печатания и совсем немного мышления, в то время как создание интерактивности приложения подразумевает более глубокий мыслительный процесс и лишь долю рутинной печати. Что ж, выясним, почему. Чтобы построить статическую версию приложения, отображающую модель данных, нам нужно создать компоненты, которые используют другие компоненты и передают данные через *пропсы*. *Пропсы* — это способ передачи данных от родителя к потомку. Если вы знакомы с понятием *состояния*, то для статической версии это как раз то, чего вам **использовать не нужно**. Состояние подразумевает собой данные, которые меняются со временем — интерактивность. Так как мы работаем над статической версией приложения, нам этого не нужно. Написание кода вы можете начать как с больших компонентов (`FilterableProductTable`), так и с малых подкомпонентов (`ProductRow`). Более простые приложения удобнее начать с компонентов, находящихся выше по иерархии. В более сложных приложениях удобнее в первую очередь создавать и тестирование подкомпоненты. -В конце этого шага у вас на руках должна быть библиотека повторно используемых компонентов, которые отображают вашу модель данных. Так как это статическая версия, компоненты будут иметь только `render()` методы. Компонент выше по иерархии (`FilterableProductTable`) будет передавать модель данных через пропсы. Если вы внесёте изменения в базовую модель данных и снова вызовете `ReactDOM.render()`, то увидите изменения интерфейса. Ничего сложного в отслеживании изменений и обновлении UI нет. Благодаря **одностороннему потоку данных** (или *односторонней привязке*), React выполняет данный процесс связанно и быстро. +В конце этого шага у вас на руках должна быть библиотека повторно используемых компонентов, которые отображают вашу модель данных. Так как это статическая версия, компоненты будут иметь только методы `render()`. Компонент выше по иерархии (`FilterableProductTable`) будет передавать модель данных через пропсы. Если вы внесете изменения в базовую модель данных и снова вызовете `ReactDOM.render()`, то увидите изменения в пользовательском интерфейсе. Ничего сложного в отслеживании изменений и обновлении интерфейса нет. Благодаря **одностороннему потоку данных** (или *односторонней привязке*), React выполняет данный процесс связанно и быстро. Если у вас остались вопросы по выполнению данного шага, обратитесь к [документации React](/docs/). @@ -97,7 +97,7 @@ prev: composition-vs-inheritance.html 2. Остаётся ли она неизменной со временем? Если это так, вероятно, это не состояние. 3. Можете ли вы вычислить её на основании любой другой части состояния или пропсах в своём компоненте? Если это так, это не состояние. -Исходный список товаров передаётся через пропсы, так что состоянием он быть не может. Поисковый запрос и чекбокс меняются со временем и не могут быть вычислены, так что они вполне сойдут за состояние. Напоследок, отфильтрованный список товаров не является состоянием, его можно вычислить методом совмещения оригинального списка, поискового запроса и значения чекбокса. +Исходный список товаров передаётся через пропсы, так что состоянием он быть не может. Поисковый запрос и чекбокс меняются со временем и не могут быть вычислены, так что они вполне сойдут за состояние. Напоследок, отфильтрованный список товаров не является состоянием, так как его можно вычислить путем сочетания оригинального списка, поискового запроса и значения чекбокса. В итоге, состоянием являются: From 1b623b315aa9088638a7cdf766cfa214e44db435 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Wed, 13 Feb 2019 13:57:32 +0000 Subject: [PATCH 12/13] Update thinking-in-react.md --- content/docs/thinking-in-react.md | 40 +++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/content/docs/thinking-in-react.md b/content/docs/thinking-in-react.md index 3d743f5ae..d2eaeec2c 100644 --- a/content/docs/thinking-in-react.md +++ b/content/docs/thinking-in-react.md @@ -33,11 +33,11 @@ prev: composition-vs-inheritance.html ## Шаг 1: Разобьём интерфейс на составляющие {#step-1-break-the-ui-into-a-component-hierarchy} -Первое, что нужно сделать — представить границы вокруг каждого компонента (и подкомпонента) в макете и дать им имена. Если вы работаете с дизайнерами, вполне возможно, что они уже как-то называют компоненты — вам стоит пообщаться! Так, слои в Photoshop отлично подходят для наименования React-компонентов. +Первое, что нужно сделать — представить границы вокруг каждого компонента (и подкомпонента) в макете и дать им имена. Если вы работаете с дизайнерами, вполне возможно, что они уже как-то называют компоненты — вам стоит пообщаться! Например, слои Photoshop часто подсказывают имена для React-компонентов. -Но как узнать, что является компонентом, а что нет? Всё очень просто: это похоже на то, как вы решаете, надо ли объявить функцию или объект. Можно применить [принцип единственной ответственности](https://ru.wikipedia.org/wiki/Принцип_единственной_ответственности): каждый компонент по-хорошему должен заниматься какой-то одной задачей. Если в конечном итоге функционал компонента увеличивается, его следует разбить на более мелкие подкомпоненты. +Но как выбрать, что является компонентом, а что нет? Это похоже на то, как вы решаете, надо ли объявить функцию или объект. Можно применить [принцип единственной ответственности](https://ru.wikipedia.org/wiki/Принцип_единственной_ответственности): каждый компонент по-хорошему должен заниматься какой-то одной задачей. Если функционал компонента увеличивается с течением времени, его следует разбить на более мелкие подкомпоненты. -Поскольку мы часто показываем модель данных JSON пользователю, вы обнаружите, что если ваша модель была построена правильно, то пользовательский интерфейс (а следовательно и структура компонентов) отобразятся надлежащим образом. Это связано с тем, что UI и модели данных имеют свойство соблюдать аналогичную *информационную архитектуру*, что значит — разделить интерфейс на составляющие не составит труда. Просто разбейте его на компоненты, каждый из которых отображает часть модели данных. +Многие интерфейсы показывают модель данных JSON. Поэтому хорошо построенная модель, как правило, напрямую отражает пользовательский интерфейс (а значит, и структуру компонентов). Интерфейс и модели данных имеют похожую *информационную архитектуру*, так что разделить интерфейс на составляющие не составляет труда. Просто разбейте его на компоненты, каждый из которых отображает часть модели данных. ![Component diagram](../images/blog/thinking-in-react-components.png) @@ -49,7 +49,7 @@ prev: composition-vs-inheritance.html 4. **`ProductCategoryRow` (голубой):** наименования *категорий* 5. **`ProductRow` (красный):** отдельно взятый *товар* -При взгляде на компонент `ProductTable` несложно заметить, что заголовок таблицы ("Name" и "Price") сам по себе отдельным компонентом не является. Отделять его или нет — вопрос личного предпочтения. В данном примере мы решили не придавать этому особого значения и оставить заголовок частью большего компонента `ProductTable`, так как он является всего лишь малой частью общего *списка данных*. Тем не менее, если в будущем заголовок пополнится новыми функциями (например, возможностью сортировать товар), имеет смысл отделить его в самостоятельный компонент `ProductTableHeader`. +Обратите внимание, что внутри `ProductTable` заголовок таблицы ("Name" и "Price") сам по себе отдельным компонентом не является. Отделять его или нет — вопрос личного предпочтения. В данном примере мы решили не придавать этому особого значения и оставить заголовок частью большего компонента `ProductTable`, так как он является всего лишь малой частью общего *списка данных*. Тем не менее, если в будущем заголовок пополнится новыми функциями (например, возможностью сортировать товар), имеет смысл извлечь его в самостоятельный компонент `ProductTableHeader`. Теперь, когда мы определили компоненты в нашем макете, давайте расположим их по порядку подчинённости. Это просто. Компоненты, которые являются частью других компонентов, в иерархии отображаются как дочерние: @@ -64,23 +64,23 @@ prev: composition-vs-inheritance.html

Пример кода Философия React: Шаг 2 на CodePen.

-Теперь, когда все компоненты расположены в иерархическом порядке, пришло время реализовать наше приложение. Самый легкий способ — создать версию, которая использует модель данных и рендерит интерфейс, но не предполагает никакой интерактивности. Разделять эти процессы полезно, поскольку написание статической версии требует много печатания и совсем немного мышления, в то время как создание интерактивности приложения подразумевает более глубокий мыслительный процесс и лишь долю рутинной печати. Что ж, выясним, почему. +Теперь, когда все компоненты расположены в иерархическом порядке, пришло время реализовать наше приложение. Самый легкий способ — создать версию, которая использует модель данных и рендерит интерфейс, но не предполагает никакой интерактивности. Разделять эти процессы полезно. Написание статической версии требует много печатания и совсем немного мышления. С другой стороны, создание интерактивности приложения подразумевает более глубокий мыслительный процесс и лишь долю рутинной печати. Мы разберёмся, почему так выходит, позже. Чтобы построить статическую версию приложения, отображающую модель данных, нам нужно создать компоненты, которые используют другие компоненты и передают данные через *пропсы*. *Пропсы* — это способ передачи данных от родителя к потомку. Если вы знакомы с понятием *состояния*, то для статической версии это как раз то, чего вам **использовать не нужно**. Состояние подразумевает собой данные, которые меняются со временем — интерактивность. Так как мы работаем над статической версией приложения, нам этого не нужно. -Написание кода вы можете начать как с больших компонентов (`FilterableProductTable`), так и с малых подкомпонентов (`ProductRow`). Более простые приложения удобнее начать с компонентов, находящихся выше по иерархии. В более сложных приложениях удобнее в первую очередь создавать и тестирование подкомпоненты. +Написание кода можно начать как сверху вниз (с большого `FilterableProductTable`), так и снизу вверх (с маленького `ProductRow`). Более простые приложения удобнее начать с компонентов, находящихся выше по иерархии. В более сложных приложениях удобнее в первую очередь создавать и тестирование подкомпоненты. -В конце этого шага у вас на руках должна быть библиотека повторно используемых компонентов, которые отображают вашу модель данных. Так как это статическая версия, компоненты будут иметь только методы `render()`. Компонент выше по иерархии (`FilterableProductTable`) будет передавать модель данных через пропсы. Если вы внесете изменения в базовую модель данных и снова вызовете `ReactDOM.render()`, то увидите изменения в пользовательском интерфейсе. Ничего сложного в отслеживании изменений и обновлении интерфейса нет. Благодаря **одностороннему потоку данных** (или *односторонней привязке*), React выполняет данный процесс связанно и быстро. +В конце этого шага у вас на руках появится библиотека повторно используемых компонентов, отображающих вашу модель данных. Так как это статическая версия, компоненты будут иметь только методы `render()`. Компонент выше по иерархии (`FilterableProductTable`) будет передавать модель данных через пропсы. Если вы внесете изменения в базовую модель данных и снова вызовете `ReactDOM.render()`, то увидите изменения в пользовательском интерфейсе. Ничего сложного в отслеживании изменений и обновлении интерфейса нет. Благодаря **одностороннему потоку данных** (или *односторонней привязке*), наш код работает быстро, но остаётся понятным. Если у вас остались вопросы по выполнению данного шага, обратитесь к [документации React](/docs/). -### Небольшое отступление: пропсы в сравнении с состоянием {#a-brief-interlude-props-vs-state} +### Небольшое отступление: как пропсы отличаются от состояния {#a-brief-interlude-props-vs-state} Существует два типа "модели" данных в React: пропсы и состояние. Важно, чтобы вы понимали разницу между ними, в противном случае обратитесь к [официальной документации React](/docs/interactivity-and-dynamic-uis.html). ## Шаг 3: Определим минимальное (но полноценное) отображение состояния интерфейса {#step-3-identify-the-minimal-but-complete-representation-of-ui-state} -Чтобы сделать наш UI интерактивным, нужно внести изменения в базовую модель данных. В React это возможно с помощью **состояния**. +Чтобы сделать наш UI интерактивным, нужно, чтобы модель данных могла меняться со временем. В React это возможно с помощью **состояния**. Чтобы правильно построить приложение, сначала нужно продумать необходимый набор данных изменяемого состояния. Главное тут следовать принципу разработки [DRY: *Don't Repeat Yourself* (рус. не повторяйся)](https://ru.wikipedia.org/wiki/Don%E2%80%99t_repeat_yourself). Определите минимальное количество необходимого состояния, которое нужно вашему приложению, всё остальное вычисляйте при необходимости. Например, если вы создаёте список дел, держите массив пунктов списка под рукой; отдельное состояние для перечисления вам не нужно. Если надо отобразить количество элементов в списке, просто используйте длину существующего массива. @@ -93,11 +93,11 @@ prev: composition-vs-inheritance.html Давайте рассмотрим каждую часть данных и определим, какая из них является состоянием. Задайте себе следующие три вопроса: - 1. Передаётся ли она от родителя через пропсы? Если это так, вероятно, это не состояние. - 2. Остаётся ли она неизменной со временем? Если это так, вероятно, это не состояние. - 3. Можете ли вы вычислить её на основании любой другой части состояния или пропсах в своём компоненте? Если это так, это не состояние. + 1. Передаётся ли она от родителя через пропсы? Тогда, наверное, это не состояние. + 2. Остаётся ли она неизменной со временем? Тогда, наверное, это не состояние. + 3. Можете ли вы вычислить её на основании любой другой части состояния или пропсах в своём компоненте? Тогда, наверное, это не состояние. -Исходный список товаров передаётся через пропсы, так что состоянием он быть не может. Поисковый запрос и чекбокс меняются со временем и не могут быть вычислены, так что они вполне сойдут за состояние. Напоследок, отфильтрованный список товаров не является состоянием, так как его можно вычислить путем сочетания оригинального списка, поискового запроса и значения чекбокса. +Исходный список товаров передаётся через пропсы, так что состоянием он быть не может. Поисковый запрос и чекбокс меняются со временем, и их нельзя вычислить из других данных, так что они вполне сойдут за состояние. Напоследок, отфильтрованный список товаров не является состоянием, так как его можно вычислить из оригинального списка, поискового запроса и значения чекбокса. В итоге, состоянием являются: @@ -110,7 +110,7 @@ prev: composition-vs-inheritance.html Итак, мы определили минимальный набор состояний приложения. Далее нам нужно выяснить, какой из компонентов *владеет* состоянием или изменяет его. -Помните: в React поток данных односторонний и сходит сверху вниз в иерархическом порядке. Изначально не совсем ясно, какой из компонентов должен владеть каким состоянием. **Зачастую это самая сложная часть для новичков.** Чтобы разобраться, следуйте этим инструкциям: +Помните: в React поток данных односторонний и сходит сверху вниз в иерархическом порядке. Сначала может быть не совсем ясно, какой из компонентов должен владеть каким состоянием. **На этом этапе новички спотыкаются чаще всего.** Чтобы разобраться, следуйте этим инструкциям: Для каждой части состояния в приложении: @@ -133,16 +133,16 @@ prev: composition-vs-inheritance.html

Пример кода Философия React: Шаг 5 на CodePen.

-До этого момента мы создавали приложение, в котором функция пропсов и состояние предаются вниз по иерархии. Теперь мы обеспечим поток данных в обратную сторону: наша задача сделать так, чтобы компоненты формы в самом низу иерархии обновляли состояние в `FilterableProductTable`. +Пока что наше приложение рендерится в зависимости от пропсов и состояния, передающихся вниз по иерархии. Теперь мы обеспечим поток данных в обратную сторону: наша задача сделать так, чтобы компоненты формы в самом низу иерархии обновляли состояние в `FilterableProductTable`. -Поток данных в React — прямой, но в связи с этим нам потребуется немного больше кода, чем в традиционной двусторонней привязке данных. +Поток данных в React — однонаправленный. Так проще понять, как работает приложение, но нам потребуется немного больше кода, чем в традиционной двусторонней привязке данных. -Если вы попытаетесь ввести текст в поисковике или установить флажок в чекбоксе данной версии примера, то увидите, что React игнорирует любой ввод. Это преднамеренно, так как ранее мы приравняли значение пропа `value` в `input` к `state` в `FilterableProductTable`. +Если вы попытаетесь ввести текст в поле поиска или установить флажок в чекбоксе данной версии примера, то увидите, что React игнорирует любой ввод. Это преднамеренно, так как ранее мы приравняли значение пропа `value` в `input` к `state` в `FilterableProductTable`. -Подумайте, какая задача стоит перед нами теперь. Нам нужно, чтобы при изменениях поисковой формы, менялось состояние ввода. Так как компоненты должны обновлять только относящееся к ним состояние, `FilterableProductTable` будет передавать колбэки в `SearchBar`, который будет срабатывать при каждом обновлении состояния. Чтобы получать уведомления об изменениях элементов формы, мы можем использовать событие `onChange`. Колбэки, переданные через компонент `FilterableProductTable`, вызовут `setState()`, и приложение обновится. +Давайте подумаем, как мы хотим изменить поведение. Нам нужно, чтобы при изменениях поисковой формы менялось состояние ввода. Так как компоненты должны обновлять только относящееся к ним состояние, `FilterableProductTable` передаст колбэк в `SearchBar`. В свою очередь, `SearchBar` будет вызывать этот колбэк каждый раз, когда надо обновить состояние. Чтобы получать уведомления об изменениях элементов формы, мы можем использовать событие `onChange`. Колбэки, переданные из компонента `FilterableProductTable`, вызовут `setState()`, и приложение обновится. -Хоть и звучит сложно, но занимает это всего несколько строк кода. А прямой поток данных через приложение от этого не меняется. +Хоть и звучит сложно, но занимает это всего несколько строк кода. А главное, поток данных через приложение остаётся прямым и понятным. ## Вот и всё {#and-thats-it} -Надеемся, что данная информация поможет вам получить лучшее представление о том, как подойти к созданию компонентов и приложений в React. Хотя этот процесс и использует немного больше кода, помните, код читают чаще, чем пишут. А такой модульный и прямой код, как в нашем приложении, читается очень легко. Когда вы начнёте создавать большие библиотеки компонентов, вы сможете по-настоящему оценить прямолинейность и связанность React, а повторно используемые компоненты сделают ваш код намного меньше. :) +Надеемся, что этот пример поможет вам получить лучшее представление о том, как подойти к созданию компонентов и приложений в React. Хотя этот процесс и использует немного больше кода, помните: код читают чаще, чем пишут. А такой модульный и прямой код, как в нашем приложении, читается очень легко. Когда вы начнёте создавать большие библиотеки компонентов, вы сможете по-настоящему оценить прямолинейность и связанность React, а повторно используемые компоненты сделают ваш код намного меньше. :) From a79465efa0532edc0ef5a7eca48065949499e02d Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Wed, 13 Feb 2019 14:06:12 +0000 Subject: [PATCH 13/13] nits --- content/docs/thinking-in-react.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/content/docs/thinking-in-react.md b/content/docs/thinking-in-react.md index d2eaeec2c..058358643 100644 --- a/content/docs/thinking-in-react.md +++ b/content/docs/thinking-in-react.md @@ -8,7 +8,7 @@ redirect_from: prev: composition-vs-inheritance.html --- -По нашему мнению, React — отличный способ создания больших и быстрых веб-приложений на основе JavaScript. Он очень хорошо масштабировался для нас в Facebook и Instagram. +Нам кажется, React — это отличный способ писать большие и быстрые JavaScript-приложения. Он очень хорошо масштабировался для нас в Facebook и Instagram. Одна из особенностей React — это то, как он предлагает думать о приложениях в процессе их создания. В этом руководстве мы покажем мысленный процесс создания таблицы продуктов с поиском на React. @@ -37,7 +37,7 @@ prev: composition-vs-inheritance.html Но как выбрать, что является компонентом, а что нет? Это похоже на то, как вы решаете, надо ли объявить функцию или объект. Можно применить [принцип единственной ответственности](https://ru.wikipedia.org/wiki/Принцип_единственной_ответственности): каждый компонент по-хорошему должен заниматься какой-то одной задачей. Если функционал компонента увеличивается с течением времени, его следует разбить на более мелкие подкомпоненты. -Многие интерфейсы показывают модель данных JSON. Поэтому хорошо построенная модель, как правило, напрямую отражает пользовательский интерфейс (а значит, и структуру компонентов). Интерфейс и модели данных имеют похожую *информационную архитектуру*, так что разделить интерфейс на составляющие не составляет труда. Просто разбейте его на компоненты, каждый из которых отображает часть модели данных. +Многие интерфейсы показывают модель данных JSON. Поэтому хорошо построенная модель, как правило, уже отражает пользовательский интерфейс (а значит, и структуру компонентов). Интерфейс и модели данных часто имеют похожую *информационную архитектуру*, так что разделить интерфейс на части не составляет труда. Просто разбейте его на компоненты, каждый из которых отображает часть модели данных. ![Component diagram](../images/blog/thinking-in-react-components.png) @@ -68,9 +68,9 @@ prev: composition-vs-inheritance.html Чтобы построить статическую версию приложения, отображающую модель данных, нам нужно создать компоненты, которые используют другие компоненты и передают данные через *пропсы*. *Пропсы* — это способ передачи данных от родителя к потомку. Если вы знакомы с понятием *состояния*, то для статической версии это как раз то, чего вам **использовать не нужно**. Состояние подразумевает собой данные, которые меняются со временем — интерактивность. Так как мы работаем над статической версией приложения, нам этого не нужно. -Написание кода можно начать как сверху вниз (с большого `FilterableProductTable`), так и снизу вверх (с маленького `ProductRow`). Более простые приложения удобнее начать с компонентов, находящихся выше по иерархии. В более сложных приложениях удобнее в первую очередь создавать и тестирование подкомпоненты. +Написание кода можно начать как сверху вниз (с большого `FilterableProductTable`), так и снизу вверх (с маленького `ProductRow`). Более простые приложения удобнее начать с компонентов, находящихся выше по иерархии. В более сложных приложениях удобнее в первую очередь создавать и тестировать подкомпоненты. -В конце этого шага у вас на руках появится библиотека повторно используемых компонентов, отображающих вашу модель данных. Так как это статическая версия, компоненты будут иметь только методы `render()`. Компонент выше по иерархии (`FilterableProductTable`) будет передавать модель данных через пропсы. Если вы внесете изменения в базовую модель данных и снова вызовете `ReactDOM.render()`, то увидите изменения в пользовательском интерфейсе. Ничего сложного в отслеживании изменений и обновлении интерфейса нет. Благодаря **одностороннему потоку данных** (или *односторонней привязке*), наш код работает быстро, но остаётся понятным. +В конце этого шага у вас на руках появится библиотека повторно используемых компонентов, отображающих вашу модель данных. Так как это статическая версия, компоненты будут иметь только методы `render()`. Компонент выше по иерархии (`FilterableProductTable`) будет передавать модель данных через пропсы. Если вы внесете изменения в базовую модель данных и снова вызовете `ReactDOM.render()`, то увидите изменения в пользовательском интерфейсе. Ничего сложного в отслеживании изменений и обновлении интерфейса нет. Благодаря **одностороннему потоку данных** (или *односторонней привязке*), код работает быстро, но остаётся понятным. Если у вас остались вопросы по выполнению данного шага, обратитесь к [документации React](/docs/). @@ -82,7 +82,7 @@ prev: composition-vs-inheritance.html Чтобы сделать наш UI интерактивным, нужно, чтобы модель данных могла меняться со временем. В React это возможно с помощью **состояния**. -Чтобы правильно построить приложение, сначала нужно продумать необходимый набор данных изменяемого состояния. Главное тут следовать принципу разработки [DRY: *Don't Repeat Yourself* (рус. не повторяйся)](https://ru.wikipedia.org/wiki/Don%E2%80%99t_repeat_yourself). Определите минимальное количество необходимого состояния, которое нужно вашему приложению, всё остальное вычисляйте при необходимости. Например, если вы создаёте список дел, держите массив пунктов списка под рукой; отдельное состояние для перечисления вам не нужно. Если надо отобразить количество элементов в списке, просто используйте длину существующего массива. +Чтобы правильно построить приложение, сначала нужно продумать необходимый набор данных изменяемого состояния. Главное тут следовать принципу разработки [DRY: *Don't Repeat Yourself* (рус. не повторяйся)](https://ru.wikipedia.org/wiki/Don%E2%80%99t_repeat_yourself). Определите минимальное количество необходимого состояния, которое нужно вашему приложению, всё остальное вычисляйте при необходимости. Например, если вы создаёте список дел, держите массив пунктов списка под рукой — но не стоит хранить отдельное состояние для количества дел в списке. Если надо отобразить количество элементов, просто используйте длину существующего массива. Давайте перечислим все данные в нашем приложении. У нас есть: @@ -95,7 +95,7 @@ prev: composition-vs-inheritance.html 1. Передаётся ли она от родителя через пропсы? Тогда, наверное, это не состояние. 2. Остаётся ли она неизменной со временем? Тогда, наверное, это не состояние. - 3. Можете ли вы вычислить её на основании любой другой части состояния или пропсах в своём компоненте? Тогда, наверное, это не состояние. + 3. Можете ли вы вычислить её на основании любой другой части состояния или пропсов в своём компоненте? Тогда, наверное, это не состояние. Исходный список товаров передаётся через пропсы, так что состоянием он быть не может. Поисковый запрос и чекбокс меняются со временем, и их нельзя вычислить из других данных, так что они вполне сойдут за состояние. Напоследок, отфильтрованный список товаров не является состоянием, так как его можно вычислить из оригинального списка, поискового запроса и значения чекбокса.