` в качестве первого дочернего элемента. Для React эти два счетчика имеют один и тот же «адрес»: первый дочерний элемент первого дочернего элемента корня. Вот как React сопоставляет их между предыдущим и следующим рендерингом, независимо от того, как вы структурируете свою логику.
-## Different components at the same position reset state {/*different-components-at-the-same-position-reset-state*/}
+## Состояние сброса разных компонентов в одном и том же положении {/*different-components-at-the-same-position-reset-state*/}
-In this example, ticking the checkbox will replace `
` with a ``:
+В этом примере установка флага заменит `` на ``:
@@ -577,13 +577,13 @@ label {
-Here, you switch between _different_ component types at the same position. Initially, the first child of the `
` contained a `Counter`. But when you swapped in a `p`, React removed the `Counter` from the UI tree and destroyed its state.
+Здесь вы переключаетесь между _различными_ типами компонентов в одной и той же позиции. Первоначально первый дочерний элемент `
` содержал `Counter`. Но когда вы заменили `p`, React удалил `Counter` из дерева UI и уничтожил его состояние.
-When `Counter` changes to `p`, the `Counter` is deleted and the `p` is added
+При изменении `Counter` на `p`, `Counter` удаляется и `p` добавляется
@@ -593,13 +593,13 @@ When `Counter` changes to `p`, the `Counter` is deleted and the `p` is added
-When switching back, the `p` is deleted and the `Counter` is added
+При обратном переключении `p` удаляется и `Counter` добавлется
-Also, **when you render a different component in the same position, it resets the state of its entire subtree.** To see how this works, increment the counter and then tick the checkbox:
+Кроме того, **когда вы визуализируете другой компонент в той же позиции, он сбрасывает состояние всего его поддерева.** Чтобы увидеть, как это работает, увеличьте счетчик и установите флажок:
@@ -688,13 +688,13 @@ label {
-The counter state gets reset when you click the checkbox. Although you render a `Counter`, the first child of the `div` changes from a `div` to a `section`. When the child `div` was removed from the DOM, the whole tree below it (including the `Counter` and its state) was destroyed as well.
+Состояние счетчика сбрасывается при установке флажка. Хотя вы рендерите `Counter`, первый дочерний элемент `div` изменяется с `div` на `section`. Когда дочерний элемент `div` был удален из DOM, все дерево под ним (включая `Counter` и его состояние) также было уничтожено.
-When `section` changes to `div`, the `section` is deleted and the new `div` is added
+При изменении `section` на `div`, `section` удаляется идобавляется `div`
@@ -704,19 +704,19 @@ When `section` changes to `div`, the `section` is deleted and the new `div` is a
-When switching back, the `div` is deleted and the new `section` is added
+При обратном переключении удаляется `div` и добавляется `section`
-As a rule of thumb, **if you want to preserve the state between re-renders, the structure of your tree needs to "match up"** from one render to another. If the structure is different, the state gets destroyed because React destroys state when it removes a component from the tree.
+Как правило, **если вы хотите сохранить состояние между повторными рендерингами, структура вашего дерева должна «сопоставляться** от одного рендеринга к другому. Если структура отличается, состояние уничтожается, потому что React уничтожает состояние, когда удаляет компонент из дерева.
-This is why you should not nest component function definitions.
+Вот почему вы не должны вкладывать определения функций компонентов.
-Here, the `MyTextField` component function is defined *inside* `MyComponent`:
+Здесь функция компонента `MyTextField` определена *внутри* `MyComponent`:
@@ -751,13 +751,13 @@ export default function MyComponent() {
-Every time you click the button, the input state disappears! This is because a *different* `MyTextField` function is created for every render of `MyComponent`. You're rendering a *different* component in the same position, so React resets all state below. This leads to bugs and performance problems. To avoid this problem, **always declare component functions at the top level, and don't nest their definitions.**
+Каждый раз, когда вы нажимаете кнопку, состояние ввода исчезает! Это связано с тем, что для каждого рендеринга `MyComponent` слздвется *другая* функция `MyTextField`. Вы визуализируете *другой* компонент в той же позиции, поэтому React сбрасывает все состояния ниже. Это приводит к ошибкам и проблемам с производительностью. Чтобы избежать этой проблемы, **всегда объявляйте функции компонентов на верхнем уровне и не вкладывайте их определения.**
-## Resetting state at the same position {/*resetting-state-at-the-same-position*/}
+## Сброс состояния в той же позиции {/*resetting-state-at-the-same-position*/}
-By default, React preserves state of a component while it stays at the same position. Usually, this is exactly what you want, so it makes sense as the default behavior. But sometimes, you may want to reset a component's state. Consider this app that lets two players keep track of their scores during each turn:
+По умолчанию React сохраняет состояние компонента, пока он остается в том же положении. Обычно это именно то, что вам нужно, поэтому это имеет смысл в качестве поведения по умолчанию. Но иногда вам может понадобиться сбросить состояние компонента. Рассмотрим это приложение, которое позволяет двум игрокам отслеживать свои очки во время каждого хода:
@@ -827,19 +827,19 @@ h1 {
-Currently, when you change the player, the score is preserved. The two `Counter`s appear in the same position, so React sees them as *the same* `Counter` whose `person` prop has changed.
+В настоящее время при смене игрока счет сохраняется. Два `Counter` появляются в одной и той же позиции, поэтому React видит их как *одно и то же* `Counter`, чье свойство `person` изменилось.
-But conceptually, in this app they should be two separate counters. They might appear in the same place in the UI, but one is a counter for Taylor, and another is a counter for Sarah.
+Но концептуально в этом приложении они должны быть двумя отдельными счетчиками. Они могут появляться в одном и том же месте пользовательского интерфейса, но один из них является счетчиком Тейлора, а другой — счетчиком Сары.
-There are two ways to reset state when switching between them:
+Существует два способа сброса состояния при переключении между ними:
-1. Render components in different positions
-2. Give each component an explicit identity with `key`
+1. Рендер компонентов в разных позициях
+2. Дать каждому компоненту явную идентичность с `key`
-### Option 1: Rendering a component in different positions {/*option-1-rendering-a-component-in-different-positions*/}
+### Вариант 1. Рендер компонента в разных позициях {/*option-1-rendering-a-component-in-different-positions*/}
-If you want these two `Counter`s to be independent, you can render them in two different positions:
+Если вы хотите, чтобы эти два `Counter` были независимыми, вы можете отображать их в двух разных позициях:
@@ -910,42 +910,42 @@ h1 {
-* Initially, `isPlayerA` is `true`. So the first position contains `Counter` state, and the second one is empty.
-* When you click the "Next player" button the first position clears but the second one now contains a `Counter`.
+* Изначально `isPlayerA` является `true`. Итак, первая позиция содержит состояние `Counter`, а вторая пуста.
+* Когда вы нажимаете кнопку «Следующий игрок», первая позиция очищается, но вторая теперь содержит `Counter`.
-Initial state
+Начальное состояние
-Clicking "next"
+Нажимаем «Далее»
-Clicking "next" again
+Нажимаем «Далее» еще раз
-Each `Counter`'s state gets destroyed each time its removed from the DOM. This is why they reset every time you click the button.
+Каждое состояние `Counter` уничтожается каждый раз, когда оно удаляется из DOM. Вот почему они сбрасываются каждый раз, когда вы нажимаете кнопку.
-This solution is convenient when you only have a few independent components rendered in the same place. In this example, you only have two, so it's not a hassle to render both separately in the JSX.
+Это решение удобно, когда у вас есть только несколько независимых компонентов, отображаемых в одном месте. В этом примере у вас есть только два, поэтому не составит труда визуализировать оба по отдельности в JSX.
-### Option 2: Resetting state with a key {/*option-2-resetting-state-with-a-key*/}
+### Вариант 2. Сброс состояния с помощью ключа {/*option-2-resetting-state-with-a-key*/}
-There is also another, more generic, way to reset a component's state.
+Существует также другой, более общий способ сброса состояния компонента.
-You might have seen `key`s when [rendering lists.](/learn/rendering-lists#keeping-list-items-in-order-with-key) Keys aren't just for lists! You can use keys to make React distinguish between any components. By default, React uses order within the parent ("first counter", "second counter") to discern between components. But keys let you tell React that this is not just a *first* counter, or a *second* counter, but a specific counter--for example, *Taylor's* counter. This way, React will know *Taylor's* counter wherever it appears in the tree!
+Возможно, вы видели `key` при [рендеринге списков.](/learn/rendering-lists#keeping-list-items-in-order-with-key) Ключи нужны не только для списков! Вы можете использовать ключи, чтобы React различал любые компоненты. По умолчанию React использует порядок внутри родителя («первый счетчик», «второй счетчик»), чтобы различать компоненты. Но ключи позволяют вам сказать React, что это не просто *первый* или *второй* счетчик, а конкретный счетчик, например, счетчик *Тейлора*. Таким образом, React будет знать счетчик *Тейлора*, где бы он ни появлялся в дереве!
-In this example, the two `
`s don't share state even though they appear in the same place in JSX:
+В этом примере два `
` не имеют общего состояния, даже если они появляются в одном и том же месте в JSX:
@@ -1015,7 +1015,7 @@ h1 {
-Switching between Taylor and Sarah does not preserve the state. This is because **you gave them different `key`s:**
+Переключение между Тейлором и Сарой не сохраняет состояние. Это потому, что **вы дали им разные `key`s:**
```js
{isPlayerA ? (
@@ -1025,19 +1025,19 @@ Switching between Taylor and Sarah does not preserve the state. This is because
)}
```
-Specifying a `key` tells React to use the `key` itself as part of the position, instead of their order within the parent. This is why, even though you render them in the same place in JSX, React sees them as two different counters, and so they will never share state. Every time a counter appears on the screen, its state is created. Every time it is removed, its state is destroyed. Toggling between them resets their state over and over.
+Указание `key` указывает React использовать `key` как часть позиции, а не их порядок внутри родителя. Вот почему, даже если вы визуализируете их в одном и том же месте в JSX, React видит их как два разных счетчика, и поэтому они никогда не будут иметь общего состояния. Каждый раз, когда счетчик появляется на экране, создается его состояние. Каждый раз, когда он удаляется, его состояние уничтожается. Переключение между ними сбрасывает их состояние снова и снова.
-Remember that keys are not globally unique. They only specify the position *within the parent*.
+Помните, что ключи не являются глобально уникальными. Они указывают только позицию *внутри родителя*.
-### Resetting a form with a key {/*resetting-a-form-with-a-key*/}
+### Сброс формы с помощью ключа {/*resetting-a-form-with-a-key*/}
-Resetting state with a key is particularly useful when dealing with forms.
+Сброс состояния с помощью ключа особенно полезен при работе с формами.
-In this chat app, the `
` component contains the text input state:
+В этом чат-приложении компонент `` содержит состояние ввода текста:
@@ -1132,17 +1132,17 @@ textarea {
-Try entering something into the input, and then press "Alice" or "Bob" to choose a different recipient. You will notice that the input state is preserved because the `` is rendered at the same position in the tree.
+Попробуйте ввести что-нибудь в поле ввода, а затем нажмите «Алиса» или «Боб», чтобы выбрать другого получателя. Вы заметите, что состояние ввода сохраняется, потому что `` отображается в той же позиции в дереве.
-**In many apps, this may be the desired behavior, but not in a chat app!** You don't want to let the user send a message they already typed to a wrong person due to an accidental click. To fix it, add a `key`:
+**Во многих приложениях это может быть желаемым поведением, но не в приложении чата!** Вы не хотите, чтобы пользователь отправил сообщение, которое он уже набрал, не тому человеку из-за случайного клика. Чтобы исправить это, добавьте `key`:
```js
```
-This ensures that when you select a different recipient, the `Chat` component will be recreated from scratch, including any state in the tree below it. React will also re-create the DOM elements instead of reusing them.
+Это гарантирует, что при выборе другого получателя компонент `Chat` компонент будет воссоздан с нуля, включая все состояния в дереве под ним. React также будет воссоздавать элементы DOM вместо их повторного использования.
-Now switching the recipient always clears the text field:
+Теперь переключение получателя всегда очищает текстовое поле:
@@ -1239,24 +1239,24 @@ textarea {
-#### Preserving state for removed components {/*preserving-state-for-removed-components*/}
+#### Сохранение состояния для удаленных компонентов {/*preserving-state-for-removed-components*/}
-In a real chat app, you'd probably want to recover the input state when the user selects the previous recipient again. There are a few ways to keep the state "alive" for a component that's no longer visible:
+В реальном приложении чата вы, вероятно, захотите восстановить состояние ввода, когда пользователь снова выбирает предыдущего получателя. Есть несколько способов сохранить состояние «живым» для компонента, который больше не виден:
-- You could render _all_ chats instead of just the current one, but hide all the others with CSS. The chats would not get removed from the tree, so their local state would be preserved. This solution works great for simple UIs. But it can get very slow if the hidden trees are large and contain a lot of DOM nodes.
-- You could [lift the state up](/learn/sharing-state-between-components) and hold the pending message for each recipient in the parent component. This way, when the child components get removed, it doesn't matter, because it's the parent that keeps the important information. This is the most common solution.
-- You might also use a different source in addition to React state. For example, you probably want a message draft to persist even if the user accidentally closes the page. To implement this, you could have the `Chat` component initialize its state by reading from the [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage), and save the drafts there too.
+- Вы можете отобразить _все_ чаты, а не только текущий, но скрыть все остальные с помощью CSS. Чаты не будут удалены из дерева, поэтому их локальное состояние будет сохранено. Это решение отлично работает для простых пользовательских интерфейсов. Но это может быть очень медленным, если скрытые деревья большие и содержат много узлов DOM.
+- Вы можете [поднять состояние](/learn/sharing-state-between-components) и сохранить ожидающее сообщение для каждого получателя в родительском компоненте. Таким образом, когда удаляются дочерние компоненты, это не имеет значения, потому что родительский компонент сохраняет важную информацию. Это наиболее распространенное решение.
+- Вы также можете использовать другой источник в дополнение к состоянию React. Например, вы, вероятно, хотите, чтобы черновик сообщения сохранялся, даже если пользователь случайно закроет страницу. Чтобы реализовать это, вы можете сделать так, чтобы `Chat` компонент инициализировал свое состояние, читая из файла [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage), и сохранял там черновики.
-No matter which strategy you pick, a chat _with Alice_ is conceptually distinct from a chat _with Bob_, so it makes sense to give a `key` to the `` tree based on the current recipient.
+Независимо от того, какую стратегию вы выберете, чат _с Алисой_ концептуально отличается от чата _с Бобом_, поэтому имеет смысл задать `key` `` на основе текущего получателя.
-- React keeps state for as long as the same component is rendered at the same position.
-- State is not kept in JSX tags. It's associated with the tree position in which you put that JSX.
-- You can force a subtree to reset its state by giving it a different key.
-- Don't nest component definitions, or you'll reset state by accident.
+- React сохраняет состояние до тех пор, пока один и тот же компонент отображается в одной и той же позиции.
+- Состояние не сохраняется в тегах JSX. Он связан с позицией дерева, в которую вы помещаете этот JSX.
+- Вы можете заставить поддерево сбросить свое состояние, назначив ему другой ключ.
+- Не вкладывайте определения компонентов, иначе вы случайно сбросите состояние.
@@ -1264,9 +1264,9 @@ No matter which strategy you pick, a chat _with Alice_ is conceptually distinct
-#### Fix disappearing input text {/*fix-disappearing-input-text*/}
+#### Исправление исчезающего ввода текста {/*fix-disappearing-input-text*/}
-This example shows a message when you press the button. However, pressing the button also accidentally resets the input. Why does this happen? Fix it so that pressing the button does not reset the input text.
+В этом примере показано сообщение при нажатии кнопки. Однако нажатие кнопки также случайно сбрасывает ввод. Почему это происходит? Исправьте, чтобы нажатие на кнопку не сбрасывало вводимый текст.
@@ -1315,9 +1315,9 @@ textarea { display: block; margin: 10px 0; }
-The problem is that `Form` is rendered in different positions. In the `if` branch, it is the second child of the ``, but in the `else` branch, it is the first child. Therefore, the component type in each position changes. The first position changes between holding a `p` and a `Form`, while the second position changes between holding a `Form` and a `button`. React resets the state every time the component type changes.
+Проблема в том, что `Form` рендерится в разных позициях. В `if` ветке это второй дочерний элемент `
`, но в `else` ветке это первый дочерний элемент. Поэтому тип компонента в каждой позиции меняется. Первая позиция меняется между удерживанием `p` и `Form`, а вторая позиция меняется между удерживанием `Form` и `button`. React сбрасывает состояние каждый раз, когда изменяется тип компонента.
-The easiest solution is to unify the branches so that `Form` always renders in the same position:
+Самое простое решение — объединить ветки так, чтобы `Form` всегда отображались в одной и той же позиции:
@@ -1363,7 +1363,7 @@ textarea { display: block; margin: 10px 0; }
-Technically, you could also add `null` before `
` in the `else` branch to match the `if` branch structure:
+Технически вы также можете добавить `null` перед `
` в ветке `else` чтобы соответствовать `if` структуре ветки:
@@ -1411,19 +1411,19 @@ textarea { display: block; margin: 10px 0; }
-This way, `Form` is always the second child, so it stays in the same position and keeps its state. But this approach is much less obvious and introduces a risk that someone else will remove that `null`.
+Таким образом, `Form` это всегда второй дочерний элемент, поэтому он остается в том же положении и сохраняет свое состояние. Но этот подход гораздо менее очевиден и повышает риск того, что кто-то другой удалит `null`.
-#### Swap two form fields {/*swap-two-form-fields*/}
+#### Поменять местами два поля формы {/*swap-two-form-fields*/}
-This form lets you enter first and last name. It also has a checkbox controlling which field goes first. When you tick the checkbox, the "Last name" field will appear before the "First name" field.
+Эта форма позволяет ввести имя и фамилию. Он также имеет флажок, определяющий, какое поле будет первым. При установке флажка поле «Фамилия» появится перед полем «Имя».
-It almost works, but there is a bug. If you fill in the "First name" input and tick the checkbox, the text will stay in the first input (which is now "Last name"). Fix it so that the input text *also* moves when you reverse the order.
+Это почти работает, но есть ошибка. Если вы заполните поле ввода «Имя» и отметите флажок, текст останется в первом поле ввода (теперь это «Фамилия»). Исправьте это так, чтобы вводимый текст *также* перемещался, когда вы меняете порядок.
-It seems like for these fields, their position within the parent is not enough. Is there some way to tell React how to match up the state between re-renders?
+Кажется, что для этих полей их положения внутри родителя недостаточно. Есть ли способ сообщить React, как сопоставить состояние между повторными рендерингами?
@@ -1487,7 +1487,7 @@ label { display: block; margin: 10px 0; }
-Give a `key` to both `` components in both `if` and `else` branches. This tells React how to "match up" the correct state for either `` even if their order within the parent changes:
+Дайте `key` обоим компонентам `` в обоих ветвях `if` и `else`. Это говорит React, как «сопоставить» правильное состояние для любого из ``, даже если их порядок внутри родителя изменится:
@@ -1549,11 +1549,11 @@ label { display: block; margin: 10px 0; }
-#### Reset a detail form {/*reset-a-detail-form*/}
+#### Сбросить форму сведений {/*reset-a-detail-form*/}
-This is an editable contact list. You can edit the selected contact's details and then either press "Save" to update it, or "Reset" to undo your changes.
+Это редактируемый список контактов. Вы можете отредактировать данные выбранного контакта, а затем либо нажать «Сохранить», чтобы обновить его, либо «Сбросить», чтобы отменить изменения.
-When you select a different contact (for example, Alice), the state updates but the form keeps showing the previous contact's details. Fix it so that the form gets reset when the selected contact changes.
+Когда вы выбираете другой контакт (например, Алису), состояние обновляется, но в форме продолжают отображаться сведения о предыдущем контакте. Исправьте, чтобы форма сбрасывалась при изменении выбранного контакта.
@@ -1705,7 +1705,7 @@ button {
-Give `key={selectedId}` to the `EditContact` component. This way, switching between different contacts will reset the form:
+Дайте `key={selectedId}` компоненту `EditContact`. Таким образом, переключение между разными контактами приведет к сбросу формы:
@@ -1858,13 +1858,13 @@ button {
-#### Clear an image while it's loading {/*clear-an-image-while-its-loading*/}
+#### Очистить изображение во время его загрузки {/*clear-an-image-while-its-loading*/}
-When you press "Next", the browser starts loading the next image. However, because it's displayed in the same `` tag, by default you would still see the previous image until the next one loads. This may be undesirable if it's important for the text to always match the image. Change it so that the moment you press "Next", the previous image immediately clears.
+Когда вы нажимаете «Далее», браузер начинает загрузку следующего изображения. Однако, поскольку оно отображается в том же теге `` по умолчанию вы все равно будете видеть предыдущее изображение, пока не загрузится следующее. Это может быть нежелательно, если важно, чтобы текст всегда соответствовал изображению. Измените его так, чтобы в тот момент, когда вы нажимаете «Далее», предыдущее изображение сразу исчезало.
-Is there a way to tell React to re-create the DOM instead of reusing it?
+Есть ли способ сказать React воссоздать DOM вместо его повторного использования?
@@ -1934,7 +1934,7 @@ img { width: 150px; height: 150px; }
-You can provide a `key` to the `` tag. When that `key` changes, React will re-create the `` DOM node from scratch. This causes a brief flash when each image loads, so it's not something you'd want to do for every image in your app. But it makes sense if you want to ensure the image always matches the text.
+Вы можете предоставить `key` тегу ``. Когда `key` изменится, React заново создаст узел `` DOM с нуля. Это вызывает краткую вспышку при загрузке каждого изображения, так что это не то, что вы хотели бы делать для каждого изображения в вашем приложении. Но это имеет смысл, если вы хотите, чтобы изображение всегда соответствовало тексту.
@@ -2002,11 +2002,11 @@ img { width: 150px; height: 150px; }
-#### Fix misplaced state in the list {/*fix-misplaced-state-in-the-list*/}
+#### Исправьте неуместное состояние в списке {/*fix-misplaced-state-in-the-list*/}
-In this list, each `Contact` has state that determines whether "Show email" has been pressed for it. Press "Show email" for Alice, and then tick the "Show in reverse order" checkbox. You will notice that it's _Taylor's_ email that is expanded now, but Alice's--which has moved to the bottom--appears collapsed.
+В этом списке у каждого `Contact` есть состояние, определяющее, была ли для него нажата кнопка «Показать электронную почту». Нажмите «Показать электронную почту» для Алисы, а затем установите флажок «Показать в обратном порядке». Вы заметите, что электронная почта _Тейлора_ теперь развернута, а электронная почта Алисы, которая переместилась в конец, выглядит свернутой.
-Fix it so that the expanded state is associated with each contact, regardless of the chosen ordering.
+Исправьте это так, чтобы развернутое состояние ассоциировалось с каждым контактом, независимо от выбранного порядка.
@@ -2096,16 +2096,16 @@ button {
-The problem is that this example was using index as a `key`:
+Проблема в том, что в этом примере индекс использовался как `key`:
```js
{displayedContacts.map((contact, i) =>
```
-However, you want the state to be associated with _each particular contact_.
+Однако вы хотите, чтобы состояние было связано с _каждым конкретным контактом_.
-Using the contact ID as a `key` instead fixes the issue:
+Вместо этого использование идентификатора контакта `key` устраняет проблему:
@@ -2193,7 +2193,7 @@ button {
-State is associated with the tree position. A `key` lets you specify a named position instead of relying on order.
+Состояние связано с позицией дерева. А `key` позволяет указать именованную позицию вместо того, чтобы полагаться на порядок.