Ответ
В React компонент перерендеривается в следующих случаях:
- Изменение состояния (
setStateили хукиuseState,useReducer) - Изменение пропсов (новые значения от родителя)
- Изменение контекста (если компонент подписан через
useContext) - Принудительный ререндер через
forceUpdate()(в классовых компонентах) - Изменение зависимостей в хуках (
useEffect,useMemo,useCallback)
Пример с состоянием:
const [count, setCount] = useState(0);
// Вызов setCount вызовет ререндер
<button onClick={() => setCount(c => c + 1)}>Increment</button>
Важно: React использует виртуальный DOM и может пропустить фактическое обновление DOM, если ничего не изменилось (shallow сравнение).
Ответ 18+ 🔞
А, слушай, ну вот эта вся магия с перерисовками в Реакте — она ж, блядь, не просто так происходит, как будто кто-то чихнул и всё обновилось. Есть чёткие правила, хуле.
Вот представь себе твой компонент — это такой упрямый мудак, который сидит и нихера не делает, пока его не пнёшь в нужное место. И мест этих, куда можно пнуть, не так уж и много, запомни:
- Состояние поменялось. Это святое, блядь. Вызвал
setStateилиuseState— всё, считай, ты крикнул «Муму!» и этот Герасим-компонент сразу в озере обновлений бултыхнется. Самый частый случай, ебать мои старые костыли. - Пропсы новые пришли. Родительский компонент решил, что пора дитёнку новую игрушку вручить. Старые пропсы и новые — это как два разных мешка, даже если внутри них один и тот же кирпич. React сравнит их поверхностно, увидит новую ссылку — и пошёл перерисовывать.
- Контекст изменился. Ну это если твой компонент сидит на подписке, как на игле, через
useContext. Шёл себе контекст, шёл, потом бац — и поменялся. Все подписчики, как один, дружно охуели и пошли перерисовываться. - Принудиловка (
forceUpdate). Это уже из арсенала классовых дедов. Типа «я сказал перерисуйся, ебаный рот, не рассуждай!». В функциональных компонентах этой хуйни нет, и слава богу. - Зависимости в хуках. Ну тут не сам компонент, но близко.
useEffect,useMemo— они ж смотрят на массив зависимостей. Изменилась там хоть одна ссылка — они такие: «окей, пацаны, пора заново вычислять/запускать сайд-эффект, а то ща будет пиздец».
Вот, смотри, простейший пример, где всё начинается:
const [count, setCount] = useState(0);
// Кликнул по кнопке — setCount вызвался — всё, пидары, понеслась. Компонент перерисуется.
<button onClick={() => setCount(c => c + 1)}>Increment</button>
И главное, что надо понять, ёпта: React — не дурак. Он не будет каждый раз реально в DOM лезть и всё ломать. Он сначала в уме (в виртуальном DOM) сравнивает, что изменилось. Если после всех его вычислений выходит, что новый виртуальный DOM такой же, как старый (shallow comparison, блядь!), то он такой: «Да похуй» — и настоящий DOM не трогает. Экономия, оптимизация, вся эта хуйня.
Так-то вот, не так всё и страшно. Главное — пни его в правильное место.