Рендерится ли дочерний React компонент, если родительский отрендерился, а пропсы не изменились?
Что проверяют
Знаете ли вы, что по умолчанию рендерится, и понимаете ли, что рендер это не изменение страницы.
Как отвечать
Да, рендерится. По умолчанию рендер родителя вызывает рендер всего поддерева, независимо от того, изменились пропсы или нет. React не сравнивает пропсы сам: он просто вызывает функции компонентов заново.
Дальше важнейшее уточнение, без которого ответ неполный: рендер это не обновление страницы. Рендер это вызов функции компонента и получение описания интерфейса. Затем React сравнивает новое описание с предыдущим и трогает страницу только там, где есть отличия. Поэтому лишний рендер обычно дёшев: считается функция, а не перерисовывается разметка.
Проблема появляется, когда рендер дорогой сам по себе: тяжёлые вычисления в теле, длинный список, глубокое дерево.
Как этого избежать:
- обёртка в мемоизацию: тогда React сравнит пропсы поверхностно и пропустит вызов, если они те же. Работает только вместе со стабильными пропсами: новый объект или новая стрелочная функция на каждом рендере сводят её на нет;
- композиция через содержимое, и это самый недооценённый приём. Элемент, переданный внутрь как содержимое, создаётся в родителе родителя и при рендере промежуточного компонента остаётся той же ссылкой. React увидит тот же элемент и не станет его перерисовывать, безо всякой мемоизации;
- опустить состояние вниз: если частое состояние живёт в маленьком компоненте, перерисовывается только он.
Полезно добавить, что компилятор React в девятнадцатой версии расставляет мемоизацию сам, и ручных обёрток становится меньше.
Где спотыкаются
Считают, что React сам сравнивает пропсы.
Путают рендер компонента с перерисовкой страницы.
Ставят мемоизацию, но передают новый объект каждый раз.
Не знают про приём с передачей содержимого.