flutter_greencat 0.1.0 flutter_greencat: ^0.1.0 copied to clipboard
A library that connects Flutter Widgets to a Greencat Store
flutter_greencat #
A set of utilities that allow you to easily consume a Greencat Store to build Flutter Widgets.
This package is built to work with Greencat. If you use the Redux library instead, check out flutter_redux.
Included Widgets #
StoreProvider
- The base Widget. It will pass the given Greencat Store to all descendants that request it.StoreBuilder
- A descendant Widget that gets the Store from aStoreProvider
and passes it to a Widgetbuilder
function.StoreConnector
- A descendant Widget that gets the Store from the nearestStoreProvider
ancestor, converts theStore
into aViewModel
with the givenconverter
function, and passes theViewModel
to abuilder
function. Any time the Store emits a change event, the Widget will automatically be rebuilt. No need to manage subscriptions!
Usage #
Let's demo the basic usage with the all-time favorite: A counter example!
import 'package:flutter/material.dart';
import 'package:greencat/greencat.dart';
import 'package:flutter_greencat/flutter_greencat.dart';
// Start by creating your normal "Greencat Setup."
//
// First, we'll create one action: Increment. Second, we need a reducer which
// can take this action and update the current count in response.
// One simple action type: Increment
enum ActionTypes { Increment }
// The action we'll dispatch
class IncrementAction extends Action<ActionTypes> {
final ActionTypes payload = ActionTypes.Increment;
final ActionTypes type = ActionTypes.Increment;
}
// The reducer, which takes the previous count and increments it in response
// to an Increment action.
int counterReducer(IncrementAction action, {int currentState}) {
switch (action.type) {
case ActionTypes.Increment:
return (currentState + 1);
default:
return currentState;
}
}
// This class represents the data that will be passed to the `builder` function.
//
// In our case, we need only two pieces of data: The current count and a
// callback function that we can attach to the increment button.
//
// The callback will be responsible for dispatching an Increment action.
//
// If you come from React, think of this as your PropTypes, but in a type-safe
// world!
class ViewModel {
final int count;
final VoidCallback onIncrementPressed;
ViewModel(
this.count,
this.onIncrementPressed,
);
factory ViewModel.fromStore(Store<int, IncrementAction> store) {
return new ViewModel(
store.state,
() => store.dispatch(new IncrementAction()),
);
}
}
void main() {
runApp(new FlutterGreencatApp());
}
class FlutterGreencatApp extends StatefulWidget {
@override
State<StatefulWidget> createState() => new FlutterGreencatAppState();
}
class FlutterGreencatAppState extends State<FlutterGreencatApp> {
// Create your store as a final variable in a base Widget. This works better
// with Hot Reload than creating it directly in the `build` function.
final Store<int, IncrementAction> store = new Store.createStore(
counterReducer,
initialState: 0,
);
@override
Widget build(BuildContext context) {
final title = 'Flutter Greencat Demo';
return new MaterialApp(
theme: new ThemeData.dark(),
title: title,
home: new StoreProvider(
// Pass the store to the StoreProvider. Any ancestor `StoreConnector`
// Widgets will find and use this value as the `Store`.
store: store,
// Our child will be a `StoreConnector` Widget. The `StoreConnector`
// will find the `Store` from the nearest `StoreProvider` ancestor,
// convert it into a ViewModel, and pass that ViewModel to the
// `builder` function.
//
// Every time the button is tapped, an action is dispatched and run
// through the reducer. After the reducer updates the state, the Widget
// will be automatically rebuilt. No need to manually manage
// subscriptions or Streams!
child: new StoreConnector<int, IncrementAction, ViewModel>(
// Convert the store into a ViewModel. This ViewModel will be passed
// to the `builder` below as the second argument.
converter: (store) => new ViewModel.fromStore(store),
// Take the `ViewModel` created by the `converter` function above and
// build a Widget with the data!
builder: (context, viewModel) {
return new Scaffold(
appBar: new AppBar(
title: new Text(title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
new Text('You have pushed the button this many times:'),
new Text(
// Grab the latest count from the ViewModel
viewModel.count.toString(),
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: new FloatingActionButton(
// Attach the ViewModel's callback to the Floating Action Button
// The callback simply dispatches the `Increment` action.
onPressed: viewModel.onIncrementPressed,
tooltip: 'Increment',
child: new Icon(Icons.add),
),
);
},
),
),
);
}
@override
void dispose() {
// A Greencat store should be closed when the application shuts down.
store.close();
super.dispose();
}
}