either_dart 1.0.0  either_dart: ^1.0.0 copied to clipboard
either_dart: ^1.0.0 copied to clipboard
Error handler library for type-safe and easy work with errors on Dart and Flutter. Either is an alternative to Nullable value and Exceptions.
import 'package:either_dart/either.dart';
import 'package:flutter/material.dart';
class Data {
  final String data;
  Data(this.data);
}
class ServerError {
  final String message;
  ServerError(this.message);
}
class Client {
  bool firstRequest = true;
  Future<Either<ServerError, Data>> getDataFromServer() async {
    await Future.delayed(const Duration(seconds: 2));
    if (!firstRequest) {
      return Right(Data("other string"));
    } else {
      firstRequest = false;
      return Left(ServerError("loss connection"));
    }
  }
}
class WidgetReceivingData extends StatefulWidget {
  @override
  createState() => _WidgetReceivingDataState();
}
class _WidgetReceivingDataState extends State<WidgetReceivingData> {
  final Client apiClient = Client();
  Future<Either<ServerError, Data>>? _load;
  @override
  void initState() {
    super.initState();
    _load = apiClient.getDataFromServer();
  }
  void reloadServerData() {
    setState(() {
      _load = apiClient.getDataFromServer();
    });
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: FutureBuilder<Either<ServerError, Data>>(
            future: _load,
            builder: (context, snapshot) {
              return Center(
                  // Error in future not handling
                  child: snapshot.hasData &&
                          snapshot.connectionState != ConnectionState.waiting
                      ? snapshot.data!.fold<Widget>(
                          (err) => ServerErrorWidget(err,
                              onReload: reloadServerData),
                          (data) => DataWidget(data))
                      : CircularProgressIndicator());
            }));
  }
}
class DataWidget extends StatelessWidget {
  final Data _data;
  const DataWidget(this._data);
  @override
  Widget build(BuildContext context) {
    return Text("Data: ${_data.data}");
  }
}
class ServerErrorWidget extends StatelessWidget {
  final ServerError _error;
  final VoidCallback onReload;
  const ServerErrorWidget(this._error, {required this.onReload});
  @override
  Widget build(BuildContext context) {
    return Column(mainAxisAlignment: MainAxisAlignment.center, children: [
      Text("Error: ${_error.message}"),
      SizedBox(height: 20),
      FlatButton(
        onPressed: onReload,
        child: Text("Try reload"),
      )
    ]);
  }
}
main() => runApp(MaterialApp(
      home: WidgetReceivingData(),
      theme: ThemeData(
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
    ));