Какие аргументы принимает setState с функцией обратного вызова в React
Что проверяют
Различаете ли вы две разные функции, которые можно передать в setState: функцию-обновитель и колбэк после применения обновления. Следом обычно спрашивают, как то же сделать в функциональном компоненте, где второго аргумента нет.
Как отвечать
В классовом компоненте сигнатура такая: this.setState(updater, callback).
- updater как объект:
{ count: 1 }поверхностно сливается с текущим состоянием; - updater как функция:
(state, props) => ({ count: state.count + 1 }). Получает актуальное состояние с учётом уже поставленных в очередь обновлений и текущие props, возвращает частичное состояние илиnull, если менять ничего не нужно; - callback: второй, необязательный аргумент. Аргументов не получает, вызывается после того, как обновление применено и компонент перерисован. Внутри уже доступен новый
this.state.
Зачем функциональная форма: обновления батчатся. Три вызова setState({ count: this.state.count + 1 }) подряд дадут плюс один, потому что все читают одно и то же старое значение, а три вызова с функцией дадут плюс три. С React 18 автоматический батчинг работает везде, в том числе в setTimeout, промисах и нативных обработчиках.
В функциональных компонентах сеттер из useState тоже принимает функцию, но аргумент у неё один, предыдущее значение: setCount(c => c + 1). Слияния нет, объект собирают сами через spread. Колбэка вторым аргументом нет, React предупредит в консоли, если его передать. Реакцию на новое значение выносят в useEffect с этим значением в зависимостях, а чаще просто вычисляют следующее значение заранее и сразу используют его.
Где спотыкаются
Называют функцию-обновитель «колбэком после обновления» и наоборот. На уточнении про аргументы это сразу видно: обновитель получает state и props, колбэк не получает ничего.
Делают в функции-обновителе побочные эффекты: запросы, логирование, мутацию состояния. В StrictMode при разработке React вызывает её дважды, и эффект сработает два раза.
Читают this.state или переменную состояния сразу после вызова сеттера и удивляются старому значению. Состояние это снимок текущего рендера, новое появится только в следующем.