Written by Hrishikesh Pathak
Routing is a vital facet of an app. Similar to if you handle the appliance state or construct the UI, you need to give ample consideration to optimizing the routing of your software. An optimized routing system helps customers navigate your app and may deal with the person state effectively.
In Flutter, there are a number of approaches to routing. Certainly one of them is go_Router
– a declarative and minimal routing system constructed on high of Flutter’s Router API. go_router
supplies a handy URL-based API to navigate between completely different screens.
On this article, we’ll enable you learn to use go_router
in Flutter. We’ll talk about the right way to use route parameters, navigate utilizing named routes, deal with 404 errors, and rather more. To get probably the most out of this text, make sure you learn it to the top.
Please comply with this GitHub hyperlink for the supply code to comply with alongside.
Including go_router to your Flutter venture
Open a terminal in your Flutter venture. Then run the next command to put in the go_router bundle in your Flutter venture.
flutter pub add go_router
This command installs the newest model of go_router
in your venture. If you wish to set up a distinct model, simply change the model quantity within the pubspec.yaml
file, and run flutter pub get
to get your required model.
Organising fundamental routing utilizing go_router
To combine go_router
in your app, change your MaterialApp
widget to MaterialApp.router
. This constructor accepts a routerConfig
property.
MaterialApp.router(
routerConfig: _router,
title: "Go router",
);
Subsequent, we’ll add a GoRouter
object _router
to the routerConfig
property. Let’s configure our GoRouter
and add the dwelling and settings routes.
remaining GoRouter _router = GoRouter(
routes: [
GoRoute(
path: "/",
builder: (context, state) => const HomePage(),
),
GoRoute(
path: "/settings",
builder: (context, state) => const SettingsPage(),
)
],
);
When somebody visits the /
route, GoRouter
returns the HomePage
widget. Equally, if somebody visits the /settings
route, GoRouter
returns the SettingsPage
widget.
Let’s see what HomePage
and SettingsPage
appear to be within the code.
class HomePage extends StatelessWidget {
const HomePage({tremendous.key});
@override
Widget construct(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Textual content("Homepage"),
),
physique: Middle(
baby: ElevatedButton(
),
),
);
}
}
class SettingsPage extends StatelessWidget {
const SettingsPage({tremendous.key});
@override
Widget construct(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: true,
title: const Textual content("Settings"),
),
physique: const Middle(
baby: Textual content("Settings Web page"),
),
);
}
}
Find out how to navigate between routes with go_router
To navigate between routes, we will use the GoRouter.of(context).go()
technique or the extra concise context.go()
technique. Let’s add this technique within the ElevatedButton
in our HomePage
widget to navigate to the /settings
route.
baby: ElevatedButton(
onPressed: () => context.go("/settings"),
baby: const Textual content("Go to Settings web page"),
),
Equally, add an ElevatedButton
within the SettingsPage
to come back again to the house /
route.
baby: ElevatedButton(
onPressed: () => context.go("/"),
baby: const Textual content("Go to dwelling web page"),
),
Subroutes in go_router
Within the above part, we outline our GoRouter
object. There, you’ll be able to observe that we put a number one /
in each route. When you want deeply nested routes, then it’s important to sort the entire route with the main /
each time. This additionally makes the routes much less organized.
GoRouter supplies a routes
argument in each GoRoute
object to group subroutes and outline nested routes extra simply.
If we convert our earlier GoRouter
object to a subroutes construction, then the brand new GoRouter
ought to appear to be this.
remaining GoRouter _router = GoRouter(
routes: [
GoRoute(
path: "/",
builder: (context, state) => const HomePage(),
routes: [
GoRoute(
path: "settings",
builder: (context, state) => const SettingsPage(),
)
],
),
],
);
Are you able to see the distinction? Now, the settings
routes stay contained in the /
routes. Subsequently, there’s no must specify a number one /
in subroutes.
Let’s take a look at one other instance in order that we will grasp the idea fully. If you wish to outline the nested route /a/b/c
, then the GoRouter object ought to appear to be this.
remaining GoRouter _newRouter = GoRouter(
routes: [
GoRoute(
path: "/",
builder: (context, state) => const HomePage(),
routes: [
GoRoute(
path: "a",
builder: (context, state) => const PageA(),
routes: [
GoRoute(
path: "b",
builder: (context, state) => PageB(),
routes: [
GoRoute(
path: "c",
builder: (context, state) => PageC(),
)
],
)
],
)
],
)
],
);
Including route parameters in go_router
It is rather simple so as to add route parameters in go_router
. To outline a route parameter, add a trailing :
with the parameter title within the path
argument of GoRoute
.
For instance, if you wish to add a title
parameter within the settings route, the path
argument needs to be /settings:title
. You’ll be able to entry the route parameter with the state.params["name"]
variable.
Let’s see the right way to implement this in our Flutter app. The modified GoRouter
with a route parameter within the settings route ought to appear to be this.
remaining GoRouter _router = GoRouter(
routes: [
GoRoute(
path: "/",
builder: (context, state) => const HomePage(),
routes: [
GoRoute(
path: "settings/:name",
builder: (context, state) => SettingsPage(
name: state.params["name"]!,
),
)
],
),
],
);
To obtain the route parameter within the settings display screen, let’s modify our code and add a property known as title
.
class SettingsPage extends StatelessWidget {
remaining String title;
const SettingsPage({tremendous.key, required this.title});
@override
Widget construct(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: true,
title: Textual content(title),
),
physique: Middle(
baby: ElevatedButton(
onPressed: () => context.go("/"),
baby: const Textual content("Go to dwelling web page"),
),
),
);
}
}
Now, after we go to /settings/codemagic
, the codemagic
route parameter is handed to the SettingsPage
and shows the variable on the display screen. Equally, in case you go to the /settings/hrishikesh
route, hrishikesh
is displayed within the SettingsPage
.
Named routes in go_router
Writing route paths manually is cumbersome and error inclined. Subsequently, go_router
provides a named route function to navigate across the app, and go_router
will routinely resolve the trail itself.
To generate named routes, let’s change our GoRouter
configuration with the title parameter.
remaining GoRouter _router = GoRouter(
routes: [
GoRoute(
name: "home",
path: "/",
builder: (context, state) => const HomePage(),
routes: [
GoRoute(
name: "settings",
path: "settings/:name",
builder: (context, state) => SettingsPage(
name: state.params["name"]!,
),
)
],
),
],
);
Passing route parameters to a named route is completely different from what you usually see. You need to outline a params
parameter within the context.goNamed()
perform. Right here’s the right way to arrange navigation to SettingsPage
from HomePage
with a route parameter.
baby: ElevatedButton(
onPressed: () => context.goNamed(
"settings",
params: {"title": "codemagic"},
),
baby: const Textual content("Go to Settings web page"),
),
Passing question parameters in go_router
You’ve got entry to queryParams
within the context.goNamed()
perform. The perfect factor about queryParams
is that you just don’t must explicitly outline them in your route path and may simply entry them utilizing the state.queryParams
technique. You’ll be able to add miscellaneous user-related knowledge as a question parameter.
Let’s take a look at an instance for example this idea. Within the ElevatedButton
in HomePage
, let’s add some question parameters to the settings route.
baby: ElevatedButton(
onPressed: () => context.goNamed("settings", params: {
"title": "codemagic"
}, queryParams: {
"e-mail": "[email protected]",
"age": "25",
"place": "India"
}),
baby: const Textual content("Go to Settings web page"),
),
Now we will entry these question parameters contained in the GoRouter
configurations and move them to the web page. On this instance, I’m simply printing out the values for demonstration.
GoRoute(
title: "settings",
path: "settings/:title",
builder: (context, state) {
state.queryParams.forEach(
(key, worth) {
print("$key:$worth");
},
);
return SettingsPage(
title: state.params["name"]!,
);
},
)
Now, if you click on the button to navigate to the SettingsPage
, you’ll be able to see the next output on the console display screen.
Dealing with 404 errors with go_router
When a person visits a display screen that’s not outlined within the GoRouter
configuration, it causes an exception. However go_router
supplies a very simple approach to deal with these errors, and you’ll present a customized web page to indicate to the person when this sort of exception happens.
We are able to outline an errorBuilder
argument within the GoRouter
object to deal with these 404 errors. Let’s make an ErrorScreen
web page that features a button to navigate again to the HomePage
.
class ErrorScreen extends StatelessWidget {
const ErrorScreen({tremendous.key});
@override
Widget construct(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: true,
title: const Textual content("Error Display screen"),
),
physique: Middle(
baby: ElevatedButton(
onPressed: () => context.go("/"),
baby: const Textual content("Go to dwelling web page"),
),
),
);
}
}
Now add this ErrorScreen
to the errorBuilder
argument of the GoRouter
object.
remaining GoRouter _router = GoRouter(
errorBuilder: (context, state) => const ErrorScreen(),
);
That’s it. Attempt to launch your Flutter app within the Chrome browser and navigate to a random path. You will note that ErrorScreen
will seem as a response.
Redirecting routes utilizing go_router
Generally, you wish to programmatically navigate your person from one web page to a different primarily based on sure logic. You’ll be able to allow that function utilizing redirects in go_router
. You’ll be able to outline a redirect for each path and a worldwide redirect for all pages.
For instance, when a brand new person opens your software, you’ll be able to navigate them to the login display screen as a substitute of the house display screen. Equally, when a logged-in person opens your software, you’ll be able to navigate them to the house web page. You’ll be able to implement this sort of function very simply utilizing go_router
.
Let’s see the right way to implement a redirect in your app. Contained in the route, outline a redirect
argument. Contained in the redirect
builder, examine if the person is logged in or not. If they don’t seem to be logged in, navigate them to the /login
web page. In any other case, present them the house web page.
remaining GoRouter _router = GoRouter(
routes: [
GoRoute(
name: "home",
path: "/",
builder: (context, state) => const HomePage(),
redirect: (context, state) {
if (userIsNotLoggedIn){
return "/login"
}
return "/"
},
),
],
errorBuilder: (context, state) => const ErrorScreen(),
);
GoRouter navigation comparability: go vs. push
GoRouter has two strategies for navigating between pages: GoRouter.of(context).go()
and GoRouter.of(context).push()
. On the floor, they give the impression of being very related, however they perform in another way. The push()
technique stacks one web page on one other in navigation, whereas the go()
technique straight navigates from one path to a different with none stacking.
Right here’s an instance to reveal this idea. Assume you have got three pages: A, B, and C. When you navigate from A to B to C utilizing the push
technique, then C is stacked on high of B on high of A. Check out this diagram to know higher.
Then again, in case you navigate from A to B to C utilizing the go
technique, then C is simply stacked on high of A and provided that A is the house web page with the route /
. B is eradicated from the navigation stack altogether. Subsequently, the go()
technique leaves no routing historical past.
You’ll be able to select which technique works greatest to your apps.
Bonus: Take away the # prefix from the online URL in Flutter
When you launch your app on the internet, you’ll be able to see a trailing #
within the URL. Generally it appears very annoying, and you could wish to take away it. You’ll be able to simply obtain this with the assistance of a bundle known as url_strategy.
First, set up this bundle in your Flutter venture.
flutter pub add url_strategy
Then import this bundle in your most important.dart
file, and add the setPathUrlStrategy()
perform earlier than the runApp()
perform.
Now, run your software. You’ll be able to see that the trailing #
is faraway from the URL of your Flutter app.
Selecting between go_router, Navigator 2.0, and Beamer for navigation in Flutter
Flutter has a number of packages you should use for routing. Probably the most well-known ones are go_router, Navigator, and Beamer. How do you select which navigation to make use of to your app?
In case you are primarily focusing on cell platforms (Android and iOS) and don’t have time to study a brand new bundle for routing, it’s fully advantageous to make use of Navigator 1.0. It’s able to assembly all of your routing wants in Android/iOS apps.
Flutter’s core energy is in its multiplatform assist, which spans past simply Android and iOS. If you wish to make an actual multiplatform app that helps desktop and net platforms along with Android/iOS, then you need to migrate to Navigator 2.0. Navigator 2.0 supplies a really versatile and absolutely customizable routing answer for actually multiplatform apps.
However an enormous chunk of builders don’t just like the verbose nature of Navigator 2.0, which often requires you to jot down boilerplate code to create a easy route. If you wish to keep away from these points, you should use go_router, which is declarative and a considerably easier answer for Flutter. If in case you have a medium-sized to giant software and wish to deal with dynamic routes, go_router
will help you reduce your effort and maximize the outcomes.
Beamer is the brand new child on the Flutter navigation stack. Like go_router
, Beamer can be primarily based on the Flutter router API. It makes builders’ lives simpler by simplifying Navigator 2.0. In case you are already utilizing go_router
, then there isn’t a want to modify to Beamer until you’re lacking some options and Beamer can fulfill your wants.
In case you are a newbie Flutter dev, you’ll be able to go along with both go_router
or Beamer. Each are good and concentrate on developer productiveness by eradicating complexity and boilerplate code.
Construct your Flutter app utilizing Codemagic
Our app isn’t fully prepared for launch at this level, however let’s arrange a CI/CD pipeline for it anyway. Ideally, you need to do that proper from the beginning of the event course of to make it simpler to collaborate on the app with different builders and ship new options to testers and clients whereas avoiding falling into the “it really works on my laptop” entice.
Codemagic is a CI/CD platform for Flutter functions. You’ll be able to set off a brand new Flutter construct if you push your code to your GitHub/GitLab/Bitbucket repository. Then simply obtain the generated artifacts from the Codemagic dashboard and run them in your units (until you wish to publish them to shops, which Codemagic also can enable you with). Let’s see step-by-step the right way to arrange a CI/CD pipeline with Codemagic to your Flutter software.
In case you aren’t a Codemagic person but, you’ll be able to enroll right here:
- Create a brand new Codemagic venture and join your repository.
- Choose Flutter because the venture sort.
- Below Automated construct triggering, examine Set off on push.
- Within the Construct tab, choose your Flutter model, construct format, and customized construct arguments.
-
Click on on the Begin new construct button to provoke the primary construct of your software.
-
After the construct completes, you’ll be able to obtain the artifacts and run the app in your units.
Conclusion
go_router
is a really minimalistic however highly effective routing bundle for Flutter. It removes all of the complexity that Flutter Navigator 2.0 brings to the desk and supplies a really developer-friendly API to work with.
On this article, we’ve got mentioned the right way to use go_router
in your Flutter app in addition to a few of its options, like route parameters, question parameters, named routes, dealing with errors, and redirection. That is only a newbie’s information for getting began with go_router
. If you wish to study extra, go to the official go_router
API documentation.
If in case you have any questions, you’ll be able to ask me on Twitter. Have day.
You will discover the pattern app on GitHub.
Hrishikesh Pathak is a Flutter developer and author. He likes to discover new know-how and write about it. Take a look at his posts on Codemagic’s weblog and his private weblog.