Skip to content

Commit

Permalink
0.4.0 - Dart2 Support with Stronger Typing
Browse files Browse the repository at this point in the history
  • Loading branch information
brianegan committed Mar 10, 2018
1 parent 500d0fe commit 5f3c6ac
Show file tree
Hide file tree
Showing 14 changed files with 18,047 additions and 202 deletions.
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ addons:
- libstdc++6
- fonts-droid
before_script:
- git clone https://github.com/flutter/flutter.git -b alpha --depth 1
- git clone https://github.com/flutter/flutter.git -b beta --depth 1
- ./flutter/bin/flutter doctor
script:
- ./flutter/bin/flutter test --coverage --coverage-path=lcov.info
- ./flutter/bin/flutter test --preview-dart-2 --coverage --coverage-path=lcov.info
after_success:
- bash <(curl -s https://codecov.io/bash)
cache:
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# Changelog

## 0.4.0

* Works with Dart 2 (no longer supports Dart 1)
* Stronger Type info Required
* Breaking Changes:
* `StoreProvider` now requires generic type info: `StoreProvider<AppState>`
* `new StoreProvider.of(context).store` is now `StoreProvider.of<AppState>(context)`

## 0.3.5

* Bugfix: `onInit` was not called before the initial ViewModel is constructed.
Expand Down
71 changes: 46 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,41 @@

A set of utilities that allow you to easily consume a [Redux](https://pub.dartlang.org/packages/redux) Store to build Flutter Widgets.

This package is built to work with [Redux.dart](https://pub.dartlang.org/packages/redux).
This package is built to work with [Redux.dart](https://pub.dartlang.org/packages/redux).

## Redux Widgets

* `StoreProvider` - The base Widget. It will pass the given Redux Store to all descendants that request it.
* `StoreBuilder` - A descendant Widget that gets the Store from a `StoreProvider` and passes it to a Widget `builder` function.
* `StoreConnector` - A descendant Widget that gets the Store from the nearest `StoreProvider` ancestor, converts the `Store` into a `ViewModel` with the given `converter` function, and passes the `ViewModel` to a `builder` function. Any time the Store emits a change event, the Widget will automatically be rebuilt. No need to manage subscriptions!

## Dart Support

* Dart 1: 0.3.x
* Dart 2: 0.4.0+. See the migration guide below!

## Examples

* [Simple example](https://gitlab.com/brianegan/flutter_redux/tree/master/example) - a port of the standard "Counter Button" example from Flutter
* [Todo app](https://gitlab.com/brianegan/flutter_architecture_samples/tree/master/example/redux) - a more complete example, with persistence, routing, and nested state.

* [Todo app](https://gitlab.com/brianegan/flutter_architecture_samples/tree/master/example/redux) - a more complete example, with persistence, routing, and nested state.
## Usage

Let's demo the basic usage with the all-time favorite: A counter example!

Note: This example requires flutter_redux 0.4.0+ and Dart 2! If you're using Dart 1, [see the old example](https://github.com/brianegan/flutter_redux/blob/eb4289795a5a70517686ccd1d161abdb8cc08af5/example/lib/main.dart).

```dart
import 'package:flutter/material.dart';
import 'package:redux/redux.dart';
import 'package:flutter_redux/flutter_redux.dart';
import 'package:redux/redux.dart';
// One simple action: Increment
enum Actions { Increment }
// The reducer, which takes the previous count and increments it in response
// to an Increment action.
int counterReducer(int state, action) {
int counterReducer(int state, dynamic action) {
if (action == Actions.Increment) {
return state + 1;
}
Expand All @@ -39,34 +47,40 @@ int counterReducer(int state, action) {
}
void main() {
runApp(new FlutterReduxApp());
// 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 = Store<int>(counterReducer, initialState: 0);
runApp(FlutterReduxApp(
title: 'Flutter Redux Demo',
store: store,
));
}
class FlutterReduxApp extends StatelessWidget {
// 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 = new Store(counterReducer, initialState: 0);
final Store<int> store;
final String title;
FlutterReduxApp({Key key, this.store, this.title}) : super(key: key);
@override
Widget build(BuildContext context) {
final title = 'Flutter Redux Demo';
return new MaterialApp(
theme: new ThemeData.dark(),
return MaterialApp(
theme: ThemeData.dark(),
title: title,
home: new StoreProvider(
// Pass the store to the StoreProvider. Any descendant `StoreConnector`
home: StoreProvider<int>(
// Pass the store to the StoreProvider. Any ancestor `StoreConnector`
// Widgets will find and use this value as the `Store`.
store: store,
child: new Scaffold(
appBar: new AppBar(
title: new Text(title),
child: Scaffold(
appBar: AppBar(
title: Text(title),
),
body: new Center(
child: new Column(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
new Text(
Text(
'You have pushed the button this many times:',
),
// Connect the Store to a Text Widget that renders the current
Expand All @@ -84,7 +98,7 @@ class FlutterReduxApp extends StatelessWidget {
// count. No need to manually manage subscriptions or Streams!
new StoreConnector<int, String>(
converter: (store) => store.state.toString(),
builder: (context, count) => new Text(
builder: (context, count) => Text(
count,
style: Theme.of(context).textTheme.display1,
),
Expand All @@ -103,11 +117,11 @@ class FlutterReduxApp extends StatelessWidget {
// with no parameters. It only dispatches an Increment action.
return () => store.dispatch(Actions.Increment);
},
builder: (context, callback) => new FloatingActionButton(
builder: (context, callback) => FloatingActionButton(
// Attach the `callback` to the `onPressed` attribute
onPressed: callback,
tooltip: 'Increment',
child: new Icon(Icons.add),
child: Icon(Icons.add),
),
),
),
Expand All @@ -117,7 +131,14 @@ class FlutterReduxApp extends StatelessWidget {
}
```

### Purpose
## Dart 2 Migration

Dart 2 requires more strict typing (yay!), and gives us the option to make getting the Store from the StoreProvider more convenient!

1. Change `new StoreProvider(...)` to `StoreProvider<StateClass>(...)` in your Widget tree.
2. Change `new StoreProvider.of(context).store` to `StoreProvider.of<StateClass>(context)` if you're directly fetching the `Store<AppState>` yourself from the `StoreProvider<AppState>`. No need to access the `store` field directly any more since Dart 2 can now infer the proper type with a static function :)

## Purpose

One question that [reasonable people might ask](https://www.reddit.com/r/FlutterDev/comments/6vscdy/a_set_of_utilities_that_allow_you_to_easily/dm3ll7d/): Why do you need all of this if `StatefulWidget` exists?

Expand Down
4 changes: 3 additions & 1 deletion analysis_options.yaml
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
analyzer:
strong-mode: true
strong-mode:
implicit-casts: false
implicit-dynamic: false
1 change: 1 addition & 0 deletions example/ios/Flutter/flutter_assets/AssetManifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
1 change: 1 addition & 0 deletions example/ios/Flutter/flutter_assets/FontManifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[{"fonts":[{"asset":"fonts/MaterialIcons-Regular.ttf"}],"family":"MaterialIcons"}]
Loading

0 comments on commit 5f3c6ac

Please sign in to comment.