greencat_epics 0.0.1

  • README.md
  • CHANGELOG.md
  • Installing
  • Versions
  • 50

Greencat Epics build status coverage report

Greencat is a Redux implementation for Dart, and specializes in synchronous updates to a store in response to actions. However, it has only limited built-in mechanisms for asynchronous operations (thunks). When one needs to handle more complex async code, such as making an api call or retrieving information from a database in response to an action, you may require a slightly more powerful toolkit. This is where Epics come in!

The best part: Epics are based on Dart Streams. This makes routine tasks easy, and complex tasks such as asynchronous error handling, cancellation, and debouncing a breeze.

Example

Let's say your app has a search box. When a user submits a search term, you dispatch a PerformSearchAction which contains the term. In order to actually listen for the PerformSearchAction and make a network request for the results, we can create an Epic!

In this instance, our Epic will need to filter all incoming actions it receives to only the Action it is interested in: the PerformSearchAction. Then, we need to make a network request using the provided search term (the payload).

Finally, we need to transform those results into a new action that contains the search results. If an error has occurred, we'll want to return a new error action so our app can respond accordingly.

Here's what this looks like in code.

import 'dart:async';
import 'package:greencat_epics/greencat_epics.dart';

class ExampleEpic extends Epic<State, Action> {
   @override
   Stream<Action> map(Stream<Action> actions, EpicStore<State, Action> store) {
    // Of all the actions that are dispatched
    return actions
      // Filter down to only PerformSearchActions 
      .where((action) => action is PerformSearchAction)
      // Then make an api call with the payload
      .asyncMap((action) => 
        // Pseudo api that returns a Future of SearchResults
        api.search(action.payload)
          .then((results) => new SearchResultsAction(results))
          .catchError((error) => new SearchErrorAction(error)));
  }
}

Connecting the Epic to the Greencat Store

Now that we've got an epic to work with, we need to wire it up to our Greencat store so it can receive a stream of actions. In order to do this, we'll employ the EpicMiddleware.

import 'package:greencat_epics/greencat_epics.dart';
import 'package:greencat/greencat.dart';

final epicMiddleware = new EpicMiddleware(new ExampleEpic());
final store = new Store.createStore(exampleReducer)
  ..addMiddleware(epicMiddleware);

Combining Epics

Rather than having one massive Epic that handles every possible type of action, it's best to break Epics down into smaller, more manageable and testable units. This way we could have a SearchEpic, a ChatEpic, and an UpdateProfileEpic, for example.

However, the EpicMiddleware accepts only one Epic. So what are we to do? Fear not: greencat_epics includes class for combining Epics together!

import 'package:greencat_epics/greencat_epics.dart';

final epic = new CombinedEpic<State, Action>([
  new SearchEpic(), 
  new ChatEpic(), 
  new UpdateProfileEpic()]);

Recipes

Cancellation

In certain cases, you may need to cancel an asynchronous task in response to a dispatched action. For example, your app begins loading data in response to a user clicking on a the search button by dispatching a PerformSearchAction, and then the user hit's the cancel button in order to correct the search term, and your app dispatches a CancelSearchAction. We want our epic to cancel the previous search in response to the action. So how can we accomplish this?

This is where streams really shine. In the following example, we'll employ the RxDart library to beef up the power of streams a bit, using the takeUntil operator.

import 'package:greencat_epics/greencat_epics.dart';
import 'package:rxdart/rxdart.dart';

// This class is almost identical to ExampleEpic above
class CancelableSearchEpic extends Epic<State, Action> {
  @override
  Stream<Action> map(Stream<Action> actions, EpicStore<State, Action> store) =>
      new Observable(actions)
        .where((action) => action is PerformSearchAction)
        .asyncMap((action) => 
          api.search(action.payload)
            .then((results) => new SearchResultsAction(results))
            .catchError((error) => new SearchErrorAction(error)))
            
        // This is the trick. We use the takeUntil operator 
        // from RxDart to cancel the async operation in response 
        // to a CancelSearchAction
        .takeUntil(actions.where((action) => action is CancelSearchAction));
}

Changelog

0.0.1

  • Initial version, includes Epic, EpicMiddleware, and CombinedEpic.
  • Basic documentation
  • Tests included!

1. Depend on it

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


dependencies:
  greencat_epics: "^0.0.1"

2. Install it

You can install packages from the command line:

with pub:


$ pub get

with Flutter:


$ flutter packages get

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

3. Import it

Now in your Dart code, you can use:


import 'package:greencat_epics/greencat_epics.dart';
        
Version Uploaded Documentation Archive
0.0.1 Jul 23, 2017 Go to the documentation of greencat_epics 0.0.1 Download greencat_epics 0.0.1 archive

Analysis

This feature is new.
We welcome feedback.
More details: scoring.

We analyzed this package, and provided a score, details, and suggestions below.

  • completed on Feb 3, 2018
  • Dart: 2.0.0-dev.20.0
  • pana: 0.10.1

Scores

Popularity:
Describes how popular the package is relative to other packages. [more]
0 / 100
Health:
Code health derived from static analysis. [more]
100 / 100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100 / 100
Overall score:
Weighted score of the above. [more]
50

Platforms

Detected platforms: Flutter, web, other

No platform restriction found in primary library package:greencat_epics/greencat_epics.dart.

Suggestions

  • The description is too short.

    Add more detail about the package, what it does and what is its target use case. Try to write at least 60 characters.

  • Package is pre-v1 release.

    While there is nothing inherently wrong with versions of 0.*.*, it usually means that the author is still experimenting with the general direction API.

  • Maintain an example.

    Create a short demo in the example/ directory to show how to use this package. Common file name patterns include: main.dart, example.dart or you could also use greencat_epics.dart.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=1.23.0 <2.0.0
greencat ^0.0.4 0.0.6
rxdart ^0.13.1 0.13.1 0.15.0
Transitive dependencies
logging 0.11.3+1
quiver_hashcode 1.0.0
tuple 1.0.1
Dev dependencies
coverage 0.9.2
test 0.12.24