flutterflutter-navigationflutter-go-router

Flutter go_router: push() vs go() and web URL changes


I am facing a use case I don't know the proper way to deal with.

Please see here the simple application I have made: https://dartpad.dev/?id=5a00b315613990d8c3ead6e26bc2df4c

This tries to simulate the typical scenario where you have a record list page with data recovered from a data base, click on one of the records, make some changes and click the "Save" button to go back to the list page and see those changes updated.

If I use context.push(), I can see the changes correctly because it returns a Future so I can wait until context.pop() is executed in the detail screen and then I run getDataFromDataBase() to refresh the data from the database.

The problem I have with using context.push() is the URL is not updated when I run this for the web.

If I use context.go() instead then the URL is properly updated but since this returns void I cannot properly wait to update the records after context.pop()

I feel I am missing something because this must be a very typical scenario. Let's see if you can point me in the right direction:

  1. Is it the expected behaviour that context.push() doesn't modify the URL?
  2. In case I use context.go() instead (which by the way seems to be the recommended way to navigate according to the official documentation since imperative navigation can cause some problems: https://pub.dev/documentation/go_router/latest/topics/Navigation-topic.html). What's the proper way to manage this scenario? How to update data after context.pop()

Thank you.


Solution

  • ATM, I'm looking for an answer to your first question myself so I can't answer that.

    As for the second one, you can work around it by creating a Promise, and pass a function fulfilling that promise into your editing dialog.

    Something like this:

    class MyPage extends StatelessWidget {
      const MyPage({super.key});
    
      @override
      Widget build(BuildContext context) {
        return Column(children: [
          // ...
          TextButton(
            onPressed: () async {
              final promise = Completer<bool>();
              context.go('/somePath', extra: promise.complete);
              final editResult = await promise.future;
              // ....
            },
            child: Text('Edit'),
          )
        ]);
      }
    }
    

    You can then pick the function up from the extra-field in your route, pass it into your dialog and call it when editing is done.