Перейти к содержимому

Блог

Миф про ре-рендеры

Вам когда-нибудь говорили, что вот так передавать массив — плохая практика?

<Component levels={[1, 2, 3]} />

Ведь массив будет пересоздаваться в JSX при каждом ре-рендере, то есть пропсы будут меняться и запускать ненужные ре-рендеры Component?

И вы наверняка слышали, что нужно использовать useMemo (const levels = useMemo(() => [1, 2, 3], [])) или объявить массив вне компонента?

Я слышала это много раз. И следовала этому принципу.

Даже когда я столкнулась с кейсами, что при передаче в пропсы ref объекта и обновлении этого объекта потом — компонент не перерисовывается, я всё равно продолжала избегать передачи вот таких массивов и объектов как пропсов. Я просто не соединила в своей голове эти две простые вещи: если обновление пропсов должно приводить к ре-рендеру, тогда это должно работать и с ref, не так ли?

Сейчас я читалю Advanced React от Nadia Makarevich, и автор пишет, что одно из главных заблуждений:

Миф про ре-рендеры: Компонент перерисовывается, когда изменились пропсы.

React обновляется, когда происходит обновление стейта. И в этом случае, он перерендерит все вложенные компоненты, изменились их пропсы или нет.

В контексте ре-рендеров, изменились пропсы компонента или нет важно только в одном случае: если этот компонент обернут в HOC React.memo.

Посмотрите на примере с кодом: https://codesandbox.io/p/sandbox/props-rerender-dcq97c.

И всё! Нужно поменять способ мышления — перенести фокус с изменения пропсов на анализ изменений стейта.

P.S. Сама я для константных объектов / массивов предпочитаю создавать constants.ts и объявлять их там, но это дело личного вкуса и никак не связано с ре-рендерами.

Любите решать задачи на интервью?

Я люблю решать задачки, особенно если они не на потерю this или какие-нибудь штуки в классах, а больше про логику и структуры данных. Так что в целом я почти всегда рада лайв-кодингу, особенно когда попадаются интересные задачи.

Поэтому когда я увидела афишу лекции «Красивые математические задачи с айтишных собеседований» с преподавателем математики Бориса Трушина (известен своим youtube-каналом, где доходчиво объясняет математику), собралась и пошла.

Было интересно, разобрали 7 задач (парочка из них никогда не была замечена на собеседованиях, но и пусть). Записываю задачи и то, что может помочь найти решение в других задачах будущей мне :)

Красные и белые колпаки

Царь решил сыграть в игру со своими мудрецами: собрал 30 мудрецов, на каждого надел красный или белый колпак. Каждый мудрец видит все остальные колпаки, но не знает цвета своего колпака. Мудрецы не могут никак подавать сигналы другим о цвете их колпаков. Они сидят в комнате, и каждую минуту туда заходит проверяющий: как только хоть один мудрец правильно назовет цвет своего колпака — все будут свободны. Если называешь неправильно — казнь. Если ни один мудрец не назовет правильно цвет своего колпака в течение дня — все будут казнены.

Пока мудрецы сидели, мимо двери проходил человек и сказал: “О, среди вас как минимум 1 белый колпак!”. Через какое-то время все люди в белых колпаках встали и правильно назвали свой цвет.

Как так получилось?

Подход

Попробовать решить задачу для простейшего случая (1 белый и все остальные красные колпаки). Затем чуть сложнее (2 белых и все остальные красные), так доходим до решения.

Обращаем внимание на то, что поменяло общее знание (когда проходящий сказал, что есть как минимум 1 белый колпак).

Когда разобьётся яйцо?

У нас есть 100-этажное здание и 2 яйца. Вам нужно определить наивысший этаж, с которого можно уронить яйцо и не разбить его — причем сделать это нужно, конечно же, за минимальное количество бросков.

(если яйцо не разбилось — его можно продолжать использовать; если разбилось — нельзя использовать, естественно)

Подход

Когда одно яйцо разбилось, вторым мы можем только перебирать подряд этажи. Можно попробовать разделить более-менее равномерно этажи на одинаковые диапазоны, и так проверять.

Но при одинаковом диапазоне (проверили сначала n, затем 2n, затем 3n) — для второго яйца количество попыток не сокращается (n - 1). Это хотелось бы оптимизировать.

Опять пробуем представить идеальный вариант: в последней попытке нам нужно проверить 1 этаж, и дальше уже от этого думаем.

Как доехать с пустым баком?

Есть круговая трасса с односторонним движением, по периметру этой трассы как-то рандомно расставлены канистры с бензином. Расстояние между канистрами может быть какое угодно, в каждой канистре может быть сколько угодно бензина, но известно, что во всех канистрах суммарно — бензина ровно на то, чтобы машина проехала круг по этой трассе. Считаем, что машина тратит бензин равномерно.

Машина с пустым баком на старте. Мы можем заглянуть во все канистры.

Нам надо доказать, что как бы ни стояли канистры и сколько бы бензина в них не было, мы можем найти канистру, стартуя с которой мы сможем проехать весь круг.

(очевидно, заливая бензин из всех встреченных по пути канистр)

Подход

Рекомендуется рисовать. Я в такие задачки не очень умею, если что, объяснение вот здесь.

Бесконечный поезд

По кольцевой железной дороге едет поезд, последний вагон которого сцеплен с первым так, что внутри можно свободно перемещаться между вагонами. Вы оказались в одном случайном вагоне и ваша задача — подсчитать их общее количество. В каждом вагоне можно включать и выключать свет, но начальное положение переключателей случайное и заранее неизвестно.

Подход

Объяснение, а вообще снова решаем для одного вагона, потом для двух, трех и тд. Надо придумать, что станет для нас маркером посещенности вагона.

Тюрьма и лампочка

В тюрьме 100 заключённых сидят по одиночным камерам. Начальник тюрьмы решил организовать такую игру. Их по одному иногда будут приводить в комнату, где нет ничего, кроме одной лампочки, которую заключённому разрешается включить или выключить. Гарантируется, что рано или поздно каждый из заключенных побывает в комнате с лампочкой сколько угодно раз. В любой момент заключённый, приведённый в комнату с лампочкой, может объявить, что все заключенные уже побывали в комнате хотя бы по одному разу. Если он прав, то всех отпустят, если нет — казнят. Заключенных собрали вместе в этой комнате, объявили правила, разрешили договориться, придумать стратегию, и, уходя, оставить выключатель в том положении, в котором захотят. Придумайте стратегию, которая позволит им освободиться

Подход

Объяснение, две вещи над которым надо подумать:

  • нам нужен человек-счетчик
  • добиться того, чтобы каждый заключенный был посчитан счётчиком только один раз

Как у вас с памятью?

Часто ли вы занимаетесь утечками памяти? Честно говоря, я — нет, но тема мне интересна. Каждый раз, когда я копаюсь в проблемах, связанных с памятью в веб-приложениях, я обнаруживаю, что надо задействовать мозг по максимуму: вспомнить, как устроена работа с памятью в JS, разобраться со всеми этими данными из Memory вкладки в DevTools, четко представлять, какие данные и когда нужны для приложения.

И каждый раз это трудно для меня. Поэтому я потихоньку начала собирать полезные материалы и примеры, чтобы проще было каждый раз нырять в эти озера памяти.

Посмотрите Memory Leaks в гайдах — это отобранные ссылки со статьями, как работает GC, как лучше отлаживаться в DevTools. Также планирую со временем добавить практические советы.

0 дней без ошибок с SVG background

У нас SVG в качестве фона сверху нашего сайта, основной фон — просто серый. Для картинки у нас такой css:

.container {
background-image: url(path/to/our.svg);
background-repeat: no-repeat;
background-size: 100% 144px;
}

Всех всё устраивает, однако подкрались праздники и дизайнерка предложила обновить картинку на более праздничную (и, конечно, добавить снег, но с ним как раз проблем не было). Дизайнерка попросила не растягивать новую картинку (как мы делаем обычно, просто растягивая её до 100%), так что обновила css:

.container {
background-image: url(path/to/holiday.svg);
background: no-repeat;
background-size: auto 144px;
background-position: left top;
}

Тестировщики протестировали, и всё улетело в предпраздничный релиз.

Пару дней спустя мне написал коллега: можем ли мы что-то сделать с нашим праздничным фоном на широких экранах? Я проверила, и это была катастрофа: на широких экранах (более чем 2500px) наш фон заканчивался на 2000px, и дальше справа было просто серое пятно.

Фикс был быстрый и простой:

.container {
background-image: url(path/to/holiday.svg);
background: repeat-x;
background-size: auto 144px;
background-position: left top;
}

Просто не забывайте: либо 100%, либо repeat.

HOC или не HOC?

В наборе кат для изучения паттернов попалась одна про Higher-Order Component(HOC) в React — truncate paragraph with HOC in React. Плюс недавно разбиралась с паттерном Декоратор, и примером применения для React как раз считается HOC.

И вот я задумалась: а действительно ли хоки актуальны?

Чаще всего я вижу хоки, когда работаю с кодом, написанным 3-4 года назад, но в новом коде я практически их не вижу. Опять же, в старой документации React есть целая страница, посвященная HOC и примерам использования, а вот в новой классной документации ничего нет.

Кажется, что кастомные хуки вытеснили хоки. Что такого особенного ты можешь сделать с HOC, что не можешь, просто написав кастомный хук?

Лично я предпочитаю кастомные хуки или даже классы с вынесенной в них бизнес-логикой. Для меня это более очевидный и поддерживаемый подход.