Что внутри компонента отвечает за изменение состояния и ререндер при взаимодействии с UI
Что проверяют
Понимаете ли вы, что перерисовку запускает не обработчик события сам по себе, а вызов сеттера состояния, и отличаете ли состояние от обычной переменной внутри компонента. По ответу видно, сможете ли вы потом искать причину лишних ререндеров.
Как отвечать
За обновление отвечает не разметка и не локальная переменная, а конкретный набор источников:
useStateиuseReducerв функциональных компонентах,this.setStateв классовых: только их вызов помечает компонент как требующий обновления;- обработчик (
onClick,onChange) всего лишь вызывает сеттер, сам он ничего не перерисовывает; - новые пропсы от родителя;
- новое значение контекста у провайдера, на который подписан компонент.
Дальше React планирует работу сам: несколько вызовов сеттера в одном обработчике сливаются в один проход, затем функция компонента вызывается заново, новое дерево сравнивается с предыдущим, и в DOM уезжает только разница.
const [count, setCount] = useState(0);
// один ререндер, а не два
const onClick = () => {
setCount(c => c + 1);
setCount(c => c + 1);
};Обычная let count = 0 в теле компонента не подходит: значение теряется при следующем вызове функции, и React про изменение не узнаёт. useRef переживает ререндер, но запись в current перерисовку не запускает, и это осознанный выбор для того, что на разметку не влияет.
Где спотыкаются
Меняют состояние на месте: items.push(x) и следом setItems(items). Ссылка прежняя, сравнение считает значение тем же, экран не обновляется. Нужен новый массив или объект.
Второе: читают состояние сразу после сеттера и удивляются старому значению. Переменная замкнута на текущий рендер, новое значение появится только в следующем вызове компонента, поэтому счётчик правильнее увеличивать функцией от предыдущего.
Третье: путают ререндер и обновление DOM. Повторный вызов функции компонента сам по себе дёшев. Дорого становится, когда внутри на каждый вызов создаётся тяжёлый объект, летит запрос или стоит эффект без списка зависимостей.