Flutter go_router, как вернуть результат на предыдущую страницу?

Я пытаюсь открыть страницу и получить возвращаемый результат с пакетом go_router. В Navigation 1.0 я использую это:

      final result = await Navigator.push(
  context,
  MaterialPageRoute(builder: (context) => const SecondRoute()),
);
// handle result

Но я не могу сделать это с помощью go_router. Любое решение или объяснение?

10 ответов

Последняя версия пакета go_router теперь поддерживает эту функцию. Чтобы передать данные при выходе из экрана, вы можете сделать это:

      context.pop('value');

И чтобы вернуть это значение, ваш код должен выглядеть так:

      String? val = await context.pushNamed('secondRoute');

Надеюсь, это поможет, спасибо

Вы можете сделать это сGoRouter.of(context).addListener.

Сначала вы отправляете свою новую страницу, а затем добавляете слушателя

      GoRouter.of(context).push("/page/${page!.id}/edit");
GoRouter.of(context).addListener(watchRouteChange);

Функция слушателя может выглядеть примерно так

        watchRouteChange() {
    if (!GoRouter.of(context).location.contains("/edit")) {  // Here you check for some changes in your route that indicate you are no longer on the page you have pushed before
      // do something
      GoRouter.of(context).removeListener(watchRouteChange); // remove listener
    }
  }


В настоящее время нет способа добиться этого с помощью . Вы можете использоватьgo_router_flowчто точно похожеgo_routerс этой поп-функцией значения.

      final bool? result = await context.push<bool>('/page2');

WidgetsBinding.instance.addPostFrameCallback((_) {
  if(result){
    print('Page returned $result');
  }
});

Вы можете использовать обратный вызов, поместив функцию в дополнительный объект при нажатии нового экрана.

Пример экрана A -push-> Screen B ->pop with result -> Screen A (получить результаты)

  1. Определите тип функции, чтобы поместить
      

typedef AddNewEventResult = void Function(Result result);


  1. Нажмите А -> Б
      

GoRoute(
path: kScreenB,
builder: (BuildContext context, GoRouterState state) => ScreenB(addNewEventResultstate.extra! as AddNewEventResult),
)


  1. Когда экран B будет готов, просто перетащите его из B в A и прикрепите результат (Результат).
      

Navigator.of(context).pop();
widget.addNewEventResult(true, Result());


Этот поток описан в документации здесь: https://gorouter.dev/user-input

Как правило, вам нужно обновить данные и вернуть некоторое значение обратно в виде маршрута с параметрами, а сам экран должен управлять обновлениями/манипулированием данными.

Я не хочу копировать их код здесь, но ответ, который вы ищете, находится на странице документации выше.

К сожалению, в настоящее время GoRouter не предоставляет искомую функциональность .

Альтернативой использованию go_router_flow является самостоятельная реализация чего-то простого путем передачи обратных вызовов в качестве дополнительного свойства в GoRouterState.

Этот дротик содержит полный пример, но суть в том, что вы определяете свои маршруты примерно так:

      GoRouter(
  initialLocation: "/",
  routes: <RouteBase>[
    GoRoute(
      path: "/second",
      builder: (_, state) {
        final params = state.extra! as SecondPageParams;

        return SecondPage(params: params);
      },
    ),
  ],
);

И определите свой аналог:

      class SecondPageParams {
  final void Function(String data) action;
  
  const SecondPageParams(this.action);
}

class SecondPage extends StatelessWidget {
  final SecondPageParams params;

  const SecondPage({super.key, required this.params});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        child: Center(
          child: ElevatedButton(
            onPressed: () {
              context.pop();
              params.action("Data from second page");
            },
            child: const Text("Pop and perform action")
          ),
        ),
      ),
    );
  }
}

Это не так чисто, как возможностьawaitаcontext.push, но это простой способ указать действие, которое вы хотитеSecondPageизвлекается из стека без необходимости полагаться на другой пакет.

в документации: https://pub.dev/documentation/go_router/latest/topics/Navigation-topic.html .

Ожидание возврата значения:

      onTap: () {
  final bool? result = await context.push<bool>('/page2');
  if(result ?? false)...
}

Возврат значения:

      onTap: () => context.pop(true)

На момент ответа только поддержка выполнения

       List<Archive> selectArchives = await Navigator.of(context).push(
            MaterialPageRoute(
                builder: (context) => const ArchiveListPage(
                    selectMode: true, canSelectCount: 1)));

       context.pop(_selectArchives);

если вы используете Gorouter, вы можете использовать

GoRouter.of(контекст).pop();

Когда вы закончите со следующим экраном, просто используйте Navigator.pop(context,true);а также trueэто то, что вы хотите отправить на предыдущий экран. Вы можете отправить все, что я использую как true для справки. Это позволит вашему resultпеременная для получения данных и выполнения чего-либо.

Другие вопросы по тегам