Перерисуется ли React-компонент при изменении пропсов?
Что проверяют
Понимаете ли вы, что триггером служит не изменение пропсов, а рендер родителя, и умеете ли работать с идентичностью значений. Это практический вопрос: от ответа зависит, сможете ли вы чинить тормозящий список, а не просто расставлять memo наугад.
Как отвечать
Да, при новых пропсах компонент перерисуется. Но ответ неполон без второй половины: он перерисуется и тогда, когда пропсы не изменились, потому что React рендерит детей вслед за родителем и сам их не сравнивает. Сравнение появляется только у React.memo, и оно поверхностное, по Object.is для каждого пропса.
Отсюда вся практика вокруг ссылок:
const Row = memo(function Row({ item, onPick }) { /* ... */ });
const onPick = useCallback((id) => select(id), []);
const value = useMemo(() => ({ user, theme }), [user, theme]);Объектные литералы, массивы, инлайновые стрелки и style={{}} создаются заново на каждом рендере, поэтому мемоизированный ребёнок всё равно перерисуется. И наоборот: если мутировать объект на месте и передать ту же ссылку, React изменений не увидит, отсюда правило неизменяемых обновлений состояния.
Где спотыкаются
Отвечают «пропсы прежние, значит рендера не будет». Будет: без memo сравнения нет вовсе. Это хорошо заметно, когда родитель хранит значение поля ввода и перерисовывает тяжёлый список на каждое нажатие клавиши.
Второе: ставят memo на компонент и продолжают передавать ему инлайновый колбэк или объект. Формально оптимизация есть, ссылки новые на каждом рендере, выигрыша ноль, а расход на сравнение добавился.
Третье: мутируют массив и вызывают сеттер с той же ссылкой, например добавляют элемент через push и передают тот же массив. Ссылка не изменилась, сравнения решают, что всё по-прежнему, и экран отстаёт от данных.