Question

How do I write a GoRouter with login and home functionality?

Answer and Explanation

To implement a GoRouter with login and home functionality, you'll need to define routes, handle authentication, and manage navigation based on the user's login status. Here's a breakdown of how to achieve this:

1. Set up GoRouter:

- First, ensure you have the `go_router` package added to your `pubspec.yaml` file. Then, create a `GoRouter` instance with your desired routes.

2. Define Routes:

- You'll need at least two routes: one for the login page and one for the home page. You might also want a route for a loading screen or error handling.

3. Implement Authentication Logic:

- Create an authentication service or provider that manages the user's login state. This could involve checking for a token, user data, or any other authentication mechanism.

4. Use `redirect` Function:

- The `redirect` function in `GoRouter` is crucial for handling authentication. It allows you to intercept navigation and redirect the user based on their login status.

5. Example Code:

import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';

// Assume you have an AuthService that manages login state
class AuthService extends ChangeNotifier {
  bool _isLoggedIn = false;
  bool get isLoggedIn => _isLoggedIn;

  Future<void> login() async {
    // Simulate login process
    await Future.delayed(Duration(seconds: 1));
    _isLoggedIn = true;
    notifyListeners();
  }

  Future<void> logout() async {
    // Simulate logout process
    await Future.delayed(Duration(seconds: 1));
    _isLoggedIn = false;
    notifyListeners();
  }
}

// Define your routes
final _router = GoRouter(
  redirect: (context, state) {
    final authService = Provider.of<AuthService>(context, listen: false);
    final isLoggedIn = authService.isLoggedIn;

    final isLoggingIn = state.fullPath == '/login';

    if (!isLoggedIn && !isLoggingIn) {
      return '/login';
    }

    if (isLoggedIn && isLoggingIn) {
      return '/home';
    }

    return null;
  },
  routes: [
    GoRoute(
      path: '/login',
      builder: (context, state) => LoginPage(),
    ),
    GoRoute(
      path: '/home',
      builder: (context, state) => HomePage(),
    ),
  ],
);

// Example Login Page
class LoginPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Login')),
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            final authService = Provider.of<AuthService>(context, listen: false);
            await authService.login();
            context.go('/home');
          },
          child: Text('Login'),
        ),
      ),
    );
  }
}

// Example Home Page
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Home')),
      body: Center(
        child: ElevatedButton(
          onPressed: () async {
            final authService = Provider.of<AuthService>(context, listen: false);
            await authService.logout();
            context.go('/login');
          },
          child: Text('Logout'),
        ),
      ),
    );
  }
}

void main() {
  runApp(ChangeNotifierProvider(create: (_) => AuthService(), child: MyApp()));
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: _router,
      title: 'GoRouter Example',
    );
  }
}

6. Explanation:

- The `AuthService` manages the login state and notifies listeners when it changes.

- The `GoRouter` uses the `redirect` function to check if the user is logged in. If not, it redirects them to the login page. If they are logged in and try to access the login page, they are redirected to the home page.

- The `LoginPage` and `HomePage` are simple widgets that demonstrate the login and logout functionality.

- The `main` function wraps the app with a `ChangeNotifierProvider` to make the `AuthService` available to all widgets.

7. Important Considerations:

- This is a basic example. In a real application, you would need to handle more complex authentication scenarios, such as token management, API calls, and error handling.

- Consider using a state management solution like Provider, Riverpod, or BLoC to manage the authentication state effectively.

- Ensure your authentication logic is secure and follows best practices.

By following these steps, you can create a robust navigation system with GoRouter that handles login and home functionality effectively.

More questions