data_state 0.3.3

  • Readme
  • Changelog
  • Installing
  • 85

data_state #

tests pub.dev license

Easily produce and consume loading/error/data states in your application.

DataState is a StateNotifier-based alternative to AsyncSnapshot.

  • Produce events from DataStateNotifier, Future, Stream, RxDart ValueStream
  • Consume events through DataStateNotifier, Stream

👩🏾‍💻 Usage #

Consuming state #

Flutter example:

(Note: This example depends on flutter_data_state which is a separate package)

@override
Widget build(BuildContext context) {
  return DataStateBuilder<List<Post>>(
    notifier: () => repo.watchPosts(),
    builder: (context, state, notifier, _) {
      return Column(
        children: [
          if (state.isLoading)
            CircularProgressIndicator(),
          if (state.hasException)
            ExceptionWidget(state.exception),
          if (state.hasModel)
            ShowPost(state.model),
        ],
      );
    }
  );
}

The notifier features a reload function, useful to restart a data loading cycle. It can be combined with a gesture detector or reloader widget:

Example 1:

GestureDetector(
  onTap: () => notifier.reload(), // will trigger a rebuild with isLoading = true
  child: _child,
)

Example 2:

RefreshIndicator(
  onRefresh: notifier.reload,
  child: _child,
),

Future & Stream input support #

This package exposes an extension on Future<T> Function() called asDataNotifier.

It allows to turn any future into a DataStateNotifier callback to leverage caching and reloading capabilities.

Example 1:

final notifier = (() => future).asDataNotifier;

Example 2:

final notifier = (() {
  if (Random().nextInt(10) > 4) {
    return Future<String>.error('Error!');
  }
  return Future.delayed(
    Duration(seconds: 1),
    () => 'HELLO RANDOM: ${Random().nextInt(100)}!',
  );
}).asDataNotifier;

Same for Streams and ValueStreams:

final notifier = (() => stream).asDataNotifier;

Consuming streams #

Want to consume events via streams?

DataStateNotifier actually exposes an RxDart ValueStream:

@override
Widget build(BuildContext context) {
  final stream = repo.watchPosts().stream;
  return StreamBuilder<List<Post>>(
    initial: stream.value,
    stream: stream,
    builder: (context, snapshot) {
      // snapshot as usual
    }
  );
}

This is the anatomy of an immutable DataState object:

final state = DataState({
  T model,
  bool isLoading = false,
  Object exception,
  StackTrace stackTrace,
});

🎸 Producing state #

Example:

DataStateNotifier<List<Post>> watchPosts() {
  final notifier = DataStateNotifier<List<Post>>(
    DataState(model: getLocalPosts()),
    reload: (notifier) async {
      notifier.state = notifier.state.copyWith(isLoading: true);
      try {
        notifier.data = await loadPosts();
      } catch (error, stackTrace) {
        notifier.data = notifier.data.copyWith(exception: error, stackTrace: stackTrace);
      }
    },
  );

  // kick off cycle
  return notifier..reload();
}

The DataStateNotifier constructor takes:

  • state as the first positional argument
  • reload and onError as optional named arguments

⁉ FAQ #

Why is DataState not a freezed union? #

This would allow us to do the following destructuring:

state.when(
  data: (data) => Text(data),
  loading: () => const CircularProgressIndicator(),
  error: (error, stackTrace) => Text('Error $error'),
);

This turns out to be impractical in data-driven Flutter apps as there are cases where we need to render loading/error messages in addition to data – not instead of data.

Does DataStateNotifier depend on Flutter? #

No. It can used with pure Dart.

➕ Collaborating #

Please use Github to ask questions, open issues and send PRs. Thanks!

📝 License #

See LICENSE

[0.3.3] - 2020-06-22 #

  • upgrade freezed

[0.3.2] - 2020-06-17 #

  • support producing events from Future and Stream

[0.3.0] - 2020-06-13 #

  • model is now a positional argument
  • Update state_notifier and rxdart

[0.2.7] - 2020-04-19 #

  • Stupid formatting fix

[0.2.6] - 2020-04-19 #

  • Fix docs/license

[0.2.5] - 2020-04-18 #

  • Rearrange project layout, add DataStateBuilder
  • Stream should dispose of notifier, not the other way round

[0.2.4] - 2020-04-16 #

  • Add onError
  • Move reload to notifier and supply it as param
  • More tests and improved docs

[0.2.3] - 2020-04-15 #

  • Change dependency to be compatible with flutter_test

[0.2.2] - 2020-04-15 #

  • Add tests
  • Improve documentation

[0.2.1] - 2020-04-03 #

  • Make stream emit a ValueStream<T> (not a ValueStream<DataState<T>>) so it plays better with AsyncSnapshot (useful for incremental upgrades)

[0.2.0] - 2020-03-23 #

  • Make model an optional argument
  • Improve docs

[0.1.1] - 2020-03-12 #

  • Make initial state optional

[0.1.0] - 2020-03-12 #

  • Add DataState immutable class carries data, loading and exception information
  • Add DataStateNotifier class, a StateNotifier for DataState objects that additionally supports a Stream API
  • Write README

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  data_state: ^0.3.3

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter pub get

Alternatively, your editor might support pub get or flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:data_state/data_state.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
74
Health:
Code health derived from static analysis. [more]
99
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
88
Overall:
Weighted score of the above. [more]
85
Learn more about scoring.

We analyzed this package on Jul 9, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.14

Health issues and suggestions

Document public APIs. (-1 points)

28 out of 28 API elements have no dartdoc comment.Providing good documentation for libraries, classes, functions, and other API elements improves code readability and helps developers find and use your API.

Maintenance suggestions

Maintain an example. (-10 points)

Create a short demo in the example/ directory to show how to use this package.

Common filename patterns include main.dart, example.dart, and data_state.dart. Packages with multiple examples should provide example/README.md.

For more information see the pub package layout conventions.

The package description is too short. (-2 points)

Add more detail to the description field of pubspec.yaml. Use 60 to 180 characters to describe the package, what it does, and its target use case.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.7.1 <3.0.0
async ^2.4.0 2.4.2
freezed_annotation ^0.11.0 0.11.0
rxdart ^0.24.1 0.24.1
state_notifier ^0.5.0 0.5.0
Transitive dependencies
collection 1.14.13 1.15.0-nullsafety
json_annotation 3.0.1
meta 1.2.2 1.3.0-nullsafety
Dev dependencies
build_runner ^1.8.0
freezed ^0.11.2
test ^1.9.4