Skip to content

Commit

Permalink
Apply suggestions from code review
Browse files Browse the repository at this point in the history
Co-authored-by: Alina Listunova <[email protected]>
  • Loading branch information
undead404 and alinkedd authored Jul 24, 2024
1 parent 70d7513 commit aa9a5cf
Showing 1 changed file with 19 additions and 19 deletions.
38 changes: 19 additions & 19 deletions src/content/learn/state-as-a-snapshot.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ title: Стан як зняток

## Задання стану запускає рендери {/*setting-state-triggers-renders*/}

Можна уявляти, що користувацький інтерфейс змінюється безпосередньо внаслідок дії користувача, наприклад, клацання. В React же це працює трохи інакше, ніж передбачає ця ментальна модель. На попередній сторінці ви побачили, що [задання стану просить React про повторний рендер](/learn/render-and-commit#step-1-trigger-a-render). Це означає, що щоб інтерфейс зреагував на подію, необхідно *оновити стан*.
Можна уявляти, що інтерфейс користувача змінюється безпосередньо внаслідок дії користувача, наприклад, клацання. У React це працює трохи інакше, ніж передбачає ця ментальна модель. На попередній сторінці ви побачили, що [задання стану просить React про повторний рендер](/learn/render-and-commit#step-1-trigger-a-render). Це означає, що необхідно *оновити стан*, щоб інтерфейс зреагував на подію.

У цьому прикладі, якщо натиснути "надіслати", то `setIsSent(true)` каже React виконати повторний рендер UI:

Expand Down Expand Up @@ -64,8 +64,8 @@ label, textarea { margin-bottom: 10px; display: block; }
Ось що відбувається, коли ви клацаєте кнопку:

1. Виконується обробник події `onSubmit`.
2. `setIsSent(true)` задає `isSent` значення `true`, і таким чином додає в чергу новий рендер.
3. React виконує повторний рендер компонента, згідно з новим значенням `isSent`.
2. `setIsSent(true)` задає `isSent` значення `true` і так додає до черги новий рендер.
3. React виконує повторний рендер компонента згідно з новим значенням `isSent`.

Погляньмо уважніше на взаємозв'язок між станом і рендерингом.

Expand Down Expand Up @@ -129,7 +129,7 @@ h1 { display: inline-block; margin: 10px; width: 30px; text-align: center; }

Зверніть увагу, що `number` збільшується лише раз за одне клацання!

**Задання стану змінює його лише для *наступного* рендеру.** Під час першого рендеру `number` був `0`. Саме тому в обробнику `onClick` того конкретного рендеру значення `number` все одно `0`, навіть після виклику `setNumber(number + 1)`:
**Задання стану змінює його лише для *наступного* рендеру.** Під час першого рендеру `number` був `0`. Саме тому в обробнику `onClick` того конкретного рендеру значення `number` все одно `0` навіть після виклику `setNumber(number + 1)`:

```js
<button onClick={() => {
Expand All @@ -139,16 +139,16 @@ h1 { display: inline-block; margin: 10px; width: 30px; text-align: center; }
}}>+3</button>
```

Ось що обробник клацання цієї кнопки каже React робити:
Ось що обробник клацання цієї кнопки запитує в React:

1. `setNumber(number + 1)`: `number``0`, тож `setNumber(0 + 1)`.
* React готується змінити `number` на `1` в наступному рендері.
* React готується змінити `number` на `1` у наступному рендері.
2. `setNumber(number + 1)`: `number``0`, тож `setNumber(0 + 1)`.
* React готується змінити `number` на `1` в наступному рендері.
* React готується змінити `number` на `1` у наступному рендері.
3. `setNumber(number + 1)`: `number``0`, тож `setNumber(0 + 1)`.
* React готується змінити `number` на `1` в наступному рендері.
* React готується змінити `number` на `1` у наступному рендері.

Навіть попри те, що ви викликали `setNumber(number + 1)` тричі, в обробнику подій *поточного рендеру* `number` завжди дорівнює `0`, тож ви задаєте стан `1` тричі. Саме тому, коли завершується виконання вашого обробника помилок, React виконує повторний рендер компонента, де `number` дорівнює `1`, а не `3`.
Навіть попри те, що ви викликали `setNumber(number + 1)` тричі, в обробнику подій *поточного рендеру* `number` завжди дорівнює `0`, тож ви задаєте стану значення `1` тричі. Саме тому, коли завершується виконання вашого обробника помилок, React виконує повторний рендер компонента, де `number` дорівнює `1`, а не `3`.

Також це можна візуалізувати, уявно замінюючи змінні стану їхніми значеннями в вашому коді. Оскільки змінна стану `number` дорівнює `0` для *поточного рендеру*, обробник подій має наступний вигляд:

Expand All @@ -170,7 +170,7 @@ h1 { display: inline-block; margin: 10px; width: 30px; text-align: center; }
}}>+3</button>
```

Саме тому клацання кнопки знову задасть лічильнику значення `2`, потім `3`після наступного клацання, і так далі.
Саме тому клацання кнопки знову задасть лічильнику значення `2`, після наступного клацання`3` і так далі.

## Стан протягом часу {/*state-over-time*/}

Expand Down Expand Up @@ -210,7 +210,7 @@ setNumber(0 + 5);
alert(0);
```

Але що якщо поставити таймер на виведення повідомлення, щоб воно спрацювало лише *після* повторного рендеру компонента? Буде "0" чи "5"? Вгадайте!
А якщо поставити таймер на виведення повідомлення, щоб воно спрацювало лише *після* повторного рендеру компонента? Буде "0" чи "5"? Вгадайте!

<Sandpack>

Expand Down Expand Up @@ -254,7 +254,7 @@ setTimeout(() => {

**Значення змінної стану ніколи не змінюється протягом одного рендеру,** навіть якщо код обробника події є асинхронним. Всередині `onClick` *поточного рендеру* значення `number` усе одно залишається `0`, навіть після виклику `setNumber(number + 5)`. Її значення "зафіксувалося", коли React "зробив зняток" UI, викликавши ваш компонент.

Ось приклад того, що робить обробники помилок більш захищеними щодо помилок хронометражу. Нижче — форма, що надсилає повідомлення з п'ятисекундною затримкою. Уявіть такий сценарій:
Ось приклад, як це захищає обробники подій від помилок хронометражу. Нижче — форма, що надсилає повідомлення з п'ятисекундною затримкою. Уявіть такий сценарій:

1. Ви натискаєте кнопку "Надіслати", надсилаючи "Привіт" Анні.
2. Перш ніж закінчиться п'ятисекундна затримка, ви змінюєте значення в полі "Кому" на "Богдан".
Expand Down Expand Up @@ -305,7 +305,7 @@ label, textarea { margin-bottom: 10px; display: block; }

</Sandpack>

**React підтримує значення стану "зафіксованими" в межах обробників подій одного рендеру.** Немає потреби перейматися тим, чи стан змінився, поки виконувався код.
**React тримає значення стану "зафіксованими" в межах обробників подій одного рендеру.** Немає потреби перейматися тим, чи стан змінився, поки виконувався код.

Але що якщо хочеться зчитати найсвіжіший стан перед повторним рендером? Знадобиться скористатися [функцією-оновлювачем стану](/learn/queueing-a-series-of-state-updates), про яку мова піде на наступній сторінці!

Expand All @@ -316,7 +316,7 @@ label, textarea { margin-bottom: 10px; display: block; }
* Коли викликається `useState`, React видає зняток стану *для конкретного поточного рендеру*.
* Змінні та обробники подій не "переживають" повторні рендери. Кожний рендер має власні обробники подій.
* Кожний рендер (а також функції в ньому) завжди "бачить" зняток стану, який React видав *цьому конкретному* рендеру.
* Можна уявно підставити стан у обробниках подій, подібного до того, як ми уявляємо JSX після рендеру.
* Можна уявно підставити стан в обробниках подій подібного до того, як ми уявляємо JSX після рендеру.
* Обробники подій, створені в минулому, мають значення стану з тих рендерів, у яких вони створені.

</Recap>
Expand Down Expand Up @@ -362,9 +362,9 @@ h1 { margin-top: 20px; }

</Sandpack>

Додайте до обробника клацання `alert`. Коли світлофор світиться зеленим і каже "Йдіть", натискання кнопки повинно видавати "Далі буде Стійте". Коли світлофор світиться червоним і каже "Стійте", натискання кнопки повинно видавати "Далі буде Йдіть".
Додайте `alert` до обробника клацання. Коли світлофор світиться зеленим і каже "Йдіть", натискання кнопки повинно видавати "Далі буде Стійте". Коли світлофор світиться червоним і каже "Стійте", натискання кнопки повинно видавати "Далі буде Йдіть".

Чи важливо те, чи поставити `alert` до виклику `setWalk`, чи після?
Чи важливий порядок: розташувати `alert` до виклику `setWalk` або навпаки?

<Solution>

Expand Down Expand Up @@ -404,17 +404,17 @@ h1 { margin-top: 20px; }

</Sandpack>

Незалежно від того, чи ви поставите виклик `alert` до виклику `setWalk`, чи після, це дасть один і той же результат. Значення `walk` у рендері — зафіксовано. Виклик `setWalk` змінить його лише для *наступного* рендеру, але не вплине на обробник подій з попереднього.
Чи ви поставите виклик `alert` до виклику `setWalk`, чи після — буде той самий результат. Значення `walk` у рендері зафіксоване. Виклик `setWalk` змінить його лише для *наступного* рендеру, але не вплине на обробник подій з попереднього.

Цей рядок може спершу здаватися контрінтуїтивним:

```js
alert(walk ? 'Далі буде Стійте' : 'Далі буде Йдіть');
```

Але він має зміст, якщо прочитати його так: "Якщо світлофор показує 'Йдіть', то повідомлення повинно звучати 'Далі буде Стійте.'". Змінна `walk` усередині вашого обробника подій відповідає значенню `walk` конкретного рендеру й не змінюється.
Але він досить логічний, якщо прочитати його так: "Якщо світлофор показує 'Йдіть', то повідомлення повинно звучати 'Далі буде Стійте.'". Змінна `walk` усередині вашого обробника подій відповідає значенню `walk` конкретного рендеру й не змінюється.

Перевірити, що це саме так, можна застосувавши підхід підстановки. Коли `walk` дорівнює `true`, вийде:
Можна перевірити, що це саме так, застосувавши метод заміни. Коли `walk` дорівнює `true`, отримаємо:

```js
<button onClick={() => {
Expand Down

0 comments on commit aa9a5cf

Please sign in to comment.