Skip to content

0.4.0 - Dart2 Support with Stronger Typing #20

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 beta --depth 1
- git clone https://github.com/flutter/flutter.git -b master --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
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# 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: `new StoreProvider<AppState>`
* `new StoreProvider.of(context).store` is now `StoreProvider.of<AppState>(context)`

## 0.3.6

* Add `onWillChange`. This function will be called before the builder and can be used for working with Imperative APIs, such as Navigator, TextEditingController, or TabController.

## 0.3.6

* Add `onWillChange`. This function will be called before the builder and can be used for working with Imperative APIs, such as Navigator, TextEditingController, or TabController.
Expand Down
70 changes: 47 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,25 @@
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).

## 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!

## Dart 2 Migration Guide

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 `new 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 :)

## Examples

* [Simple example](https://gitlab.com/brianegan/flutter_redux/tree/master/example) - a port of the standard "Counter Button" example from Flutter
Expand All @@ -26,17 +38,19 @@ This package is built to work with [Redux.dart](https://pub.dartlang.org/package

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 @@ -45,23 +59,29 @@ 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(new 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(),
title: title,
home: new StoreProvider(
// Pass the store to the StoreProvider. Any descendant `StoreConnector`
home: new 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(
Expand Down Expand Up @@ -90,10 +110,12 @@ 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(
count,
style: Theme.of(context).textTheme.display1,
),
builder: (context, count) {
return new Text(
count,
style: Theme.of(context).textTheme.display1,
);
},
)
],
),
Expand All @@ -109,21 +131,23 @@ class FlutterReduxApp extends StatelessWidget {
// with no parameters. It only dispatches an Increment action.
return () => store.dispatch(Actions.Increment);
},
builder: (context, callback) => new FloatingActionButton(
// Attach the `callback` to the `onPressed` attribute
onPressed: callback,
tooltip: 'Increment',
child: new Icon(Icons.add),
),
builder: (context, callback) {
return new FloatingActionButton(
// Attach the `callback` to the `onPressed` attribute
onPressed: callback,
tooltip: 'Increment',
child: new Icon(Icons.add),
);
},
),
),
),
);
}
}
```
```

### Purpose
## 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