Easy Way to Create a Good Error-Handling in Flutter with Dartz
Tags: flutter, programming, dart, mobile
Published: 2022-05-06 14:28:51

As developers, our main task is to create applications to solve certain problems. When published, the application we develop may produce some errors in front of the user. For example, maybe our users enter data incorrectly, the connection is lost, or even our server is down.

A good application will be able to handle the error and can point the user on the right path again. We certainly don’t want just because the app can’t handle minor errors like lost connection, the user decides to uninstall it.

In this article, I will show how to create good error handling in a Flutter project using [Dartz](https://pub.dev/packages/dartz).

## Implementation

First things first, we need to figure out what errors are possible that will happen. In a login flow, for example, the common error is:

- User inputs wrong password or email not registered
- The server maybe had a problem
- Lost internet connection

Now, let’s add the package that we need to the `pubspec.yaml` file:

```yaml
...
dependencies:
    flutter:
        sdk: flutter
    
    dartz: ^0.10.1
    ...
```

Inside the Dartz package, we will use something called `Either<L,R>` class. This class will be used to **return 2 different** things in a function.

```dart
/// Create variety of exceptions
/// Enum to help create conditions
enum LoginFailure { invalidCredentials, error }

/// Repository
/// This class can be consumed by controller, provider, or other state management later
class SomeRepository {
  final http.Client _client;
  
  Future<Either<LoginFailure, bool>> login(String email, String password) async {
    final _response = await _client.post(
      Uri.parse(Urls.nowPlayingMovies),
      body: {'email': email, 'password': password}
    );

    if (_response.statusCode == 201) {
      return Right(true);
    } else if (_response.statusCode == 400) {
      return Left(LoginFailure.invalidCredentials);
    } else {
      return Left(LoginFailure.error);
    }
  }
  
  ...
}
```

There is a function with the type `Future<Either<LoginFailure, bool>>`. With that type, now I can return 2 different things out of that function. When the request is successful (with status code 200), boolean true will be returned as the right value. If a request failed, I can easily handle it by returning the enum as the left value. The enum class act as a helper to create conditions.

And this is the way we consume the login function, for example in a `controller`:

```dart
class SomeController {
  Future login(String email, String password) async {
    final _result = await _repository.login(email, password);
    _result.fold(
      (l) {
        /// Handle left
        /// For example: show dialog or alert
      },
      (r) {
        /// Handle right
        /// For example: navigate to home page
      },
    );
  }
}
```

Now you can create some user interactions like this.

![Example user interactions to handle some errors](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5rlvufo0fkfofq5elu93.png)

## Recap

So, that's the way to implement a good error-handling on Flutter. The term good means our app has more rich error-handling to help the user understand if there is something wrong when they use the app.

Thanks for reading. I hope these short tips can help you write a more clean, concise, and robust codebase for your Flutter project.

If you find this article helpful, please leave some reaction badges for me, if you don’t mind. Also, follow me to get updates about my latest articles in the future.