You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Переключение вкладок ощущается таким медленным потому, что оно вынуждает перезапускаться замедленную функцию `filterTodos` каждый раз, когда изменяется значение `tab`. (Если интересно, почему она запускается дважды, объяснение можно найти [здесь](#my-calculation-runs-twice-on-every-re-render).)
175
175
176
-
**Однако изменение темы, благодаря `useMemo`, происходит быстро (несмотря на искусственное замедление).**Вызов функции`filterTodos` был пропущен потому, что ни`todos`, ни`tab`, указанные как зависимости в`useMemo`, никак не изменились с предыдущего рендера.
176
+
Переключите тему. **Благодаря `useMemo` это происходит быстро (несмотря на искусственное замедление).**Медленный вызов`filterTodos` был пропущен, потому что и`todos`, и`tab` (которые вы передаете как зависимости для`useMemo`) не изменились с момента последнего рендера.
177
177
178
178
<Sandpack>
179
179
@@ -303,7 +303,7 @@ label {
303
303
304
304
В данном примере функция `filterTodos` также замедлена, чтобы показать, что случается в том случае, если вызываемая во время рендера функция действительно медленная. Попробуйте попереключаться между вкладками и попереключать тему.
305
305
306
-
Поскольку в этом примере отсутствует вызов `useMemo`, то искусственно замедленная функция `filterTodos` вызывается при каждом ререндере (даже в том случае, если изменилось только значение `theme`).
306
+
Поскольку **в этом примере отсутствует вызов `useMemo`**, то искусственно замедленная функция `filterTodos` вызывается при каждом ререндере (даже в том случае, если изменилось только значение `theme`).
JSX-узел `<List items={visibleTodos} />` является простым объектом типа `{ type: List, props: { items: visibleTodos } }`. Создание такого объекта – довольно дешёвая операция, однако React не знает, осталось ли его содержимое прежним или нет. Поэтому по умолчанию React всегда будет ререндерить компонент `List`.
635
635
636
-
При этом, если React видит тот же JSX, который был при предыдущем рендере, он не будет ререндерить компонент. Так происходит потому, что JSX-узлы являются [неизменяемыми объектами](https://ru.wikipedia.org/wiki/%D0%9D%D0%B5%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D1%8F%D0%B5%D0%BC%D1%8B%D0%B9_%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82). Такие объекты не могут быть изменены с течением времени, поэтому React знает, что пропустить ререндер – безопасно. Однако чтобы это работало, узел должен быть *буквально тем же объектом*, а не только *выглядеть* таким же в коде. Это именно то, что делает `useMemo` в данном примере.
636
+
При этом, если React видит тот же JSX, который был при предыдущем рендере, он не будет ререндерить компонент. Это происходит потому что JSX-узлы [иммутабельны](https://ru.wikipedia.org/wiki/%D0%9D%D0%B5%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D1%8F%D0%B5%D0%BC%D1%8B%D0%B9_%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82). Такие объекты узлов не могут быть изменены с течением времени, поэтому React знает, что пропустить ререндер безопасно. Однако чтобы это работало, узел должен быть *буквально тем же объектом*, а не только *выглядеть* таким же в коде. Это именно то, что делает `useMemo` в данном примере.
637
637
638
638
Оборачивать JSX-узлы в `useMemo` не всегда удобно. Например, это нельзя делать по условию. По этой причине компоненты чаще оборачивают в [`memo`](/reference/react/memo).
0 commit comments