Код-ревью Middle Навигация обновлено
Код-ревью: навигация после запроса
Вопрос
Обработчик кнопки «Оплатить». Найдите проблемы.
Future<void> _pay() async {
final ok = await api.pay(widget.order);
if (ok) {
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => SuccessPage(order: widget.order),
));
} else {
Navigator.of(context).pushNamed('/error');
}
}
@override
Widget build(BuildContext context) {
if (widget.order.paid) {
Navigator.of(context).pushReplacementNamed('/home');
}
return ElevatedButton(onPressed: _pay, child: const Text('Оплатить'));
}
Коротко
Навигация это побочный эффект: вызывается из обработчиков и слушателей, не из build, и после await всегда с проверкой mounted. Экран оплаты после успеха убирается из стека.
Что должен найти ревьюер
- Ошибкастрока 4После
awaitнет проверкиmounted: пользователь мог уйти, иcontextуже недействителен. - Ошибкастрока 4После успешной оплаты
pushоставляет экран оплаты в стеке: «назад» вернёт к кнопке «Оплатить» и позволит оплатить повторно. НуженpushReplacementили переход через роутер. - Ошибкастрока 2Кнопку можно нажать дважды, пока идёт запрос: нужна блокировка и индикатор, иначе двойная оплата.
- Ошибкастрока 15Навигация прямо в
build: побочный эффект при каждом перестроении и ошибка «setState or markNeedsBuild called during build». Перенести в слушатель состояния илиredirect. - Стильстрока 5В
SuccessPageпередаётся объект заказа целиком: экран не восстановится по диплинку и после перезапуска. Лучше передать id.
Разбор
Навигация это побочный эффект: вызывается из обработчиков и слушателей, не из build, и после await всегда с проверкой mounted. Экран оплаты после успеха убирается из стека. Повторное нажатие блокируется на время запроса, а сервер ещё и защищается ключом идемпотентности.
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.