@@ -10,13 +10,25 @@ Inspired by [redux][redux_git]
1010
1111Built using [ built_value] [ built_value_git ]
1212
13- ## Framework bindings & examples
13+ ## Framework bindings
1414
1515[ flutter] [ flutter ]
1616
17- [ react-dart ] [ react-dart ]
17+ ## examples
1818
19- [ angular2] [ angular2 ]
19+ [ nested state & actions] [ nesting ]
20+
21+ [ building reducers for built collections] [ collection_reducers ]
22+
23+ [ inheritence in state & actions] [ inheritence ]
24+
25+ ## libraries
26+
27+ [ thunk] [ built_redux_thunk ]
28+
29+ [ rx] [ built_redux_rx ]
30+
31+ [ repatch] [ built_redux_repatch ]
2032
2133## Using it in your project
2234
@@ -29,10 +41,9 @@ Built using [built_value][built_value_git]
2941> gain familiarity with it by reading [ this blog post] [ built_value_blog ] .
3042
31431 . Add the ` built_redux ` package as a dependency in your ` pubspec.yaml ` .
32-
3344 ``` yaml
3445 dependencies :
35- built_redux : " ^6 .0.0"
46+ built_redux : " ^7 .0.0"
3647 ` ` `
3748
38492. Create a script to run generators for generating built_values and built_redux action classes.
@@ -44,51 +55,52 @@ Built using [built_value][built_value_git]
4455 import 'package:source_gen/source_gen.dart';
4556 import 'package:built_redux/generator.dart';
4657
47- /// Build the generated files in the built_value chat example.
4858 Future main(List<String> args) async {
4959 await build([
5060 new BuildAction(
5161 new PartBuilder([
5262 new BuiltValueGenerator(),
5363 new BuiltReduxGenerator(),
5464 ]),
65+ // your lib name here
5566 ' built_redux' ,
56- inputs : const ['test/unit/test_counter.dart'])
67+ // tweak the files that invoke the generator here
68+ inputs : const ['lib/**/*.dart'])
5769 ], deleteFilesByDefault : true);
5870 }
5971 ```
6072
61- 3 . Run the build script from the command line to generate your built_values and built_redux action classes
62- ``` dart tool/build.dart ```
73+ 3 . Run the build script from the command line to generate your built_values and built_redux action classes by running ` dart [build script name].dart `
6374
64- ### Writing a built_redux store
75+ ### Implementing a built_redux store
6576
6677``` dart
6778import 'package:built_value/built_value.dart';
6879import 'package:built_redux/built_redux.dart';
6980
70- // This is a an implementation of ReduxActions. Actions are what middleware and ui
71- // components invoke a change to the redux store's state. By extending ReduxActions
72- // the built_redux generator will generate the required boilerplate to create
73- // each action and an ActionNames class.
74- abstract class CounterActions extends ReduxActions {
75- ActionDispatcher<int> increment;
76- ActionDispatcher<int> decrement;
77-
78- // factory to create on instance of the generated implementation of CounterActions
79- CounterActions._();
80- factory CounterActions() => new _$CounterActions();
81- }
81+ // This is a an implementation of ReduxActions. Actions are what middleware and ui
82+ // components invoke a change to the redux store's state. By extending ReduxActions
83+ // the built_redux generator will generate the required boilerplate to create
84+ // each action and an ActionNames class. The ActionNames class is used to register
85+ // reducers
86+ abstract class CounterActions extends ReduxActions {
87+ ActionDispatcher<int> get increment;
88+ ActionDispatcher<int> get decrement;
89+
90+ // factory to create on instance of the generated implementation of CounterActions
91+ CounterActions._();
92+ factory CounterActions() => new _$CounterActions();
93+ }
8294
83- // This is a built value. It is an immutable model that implements the Built interface.
84- // All of the state in your redux store is contained in a single built value model.
85- abstract class Counter implements Built<Counter, CounterBuilder> {
86- /// [count] value of the counter
87- int get count;
95+ // This is a built value. It is an immutable model that implements the Built interface.
96+ // All of the state in your redux store is contained in a single built value model.
97+ abstract class Counter implements Built<Counter, CounterBuilder> {
98+ /// [count] value of the counter
99+ int get count;
88100
89- // Built value constructor. The factory is returning the default state
90- Counter._();
91- factory Counter() => new _$Counter._(count: 1);
101+ // Built value constructor. The factory is returning the default state
102+ Counter._();
103+ factory Counter() => new _$Counter._(count: 1);
92104 }
93105
94106
@@ -101,19 +113,19 @@ increment(Counter state, Action<int> action, CounterBuilder builder) =>
101113decrement(Counter state, Action<int> action, CounterBuilder builder) =>
102114 builder.count = state.count - action.payload;
103115
104- // This is a reducer builder. Use of ReducerBuilder is not required, however it
105- // is strongly recommended as it gives you static type checking to make sure
106- // the payload for action name provided is the same as the expected payload
107- // for the action provided to your reducer. Calling .build() returns a reducer function
108- // that can be passed to the store's constructor.
109- var reducer = ( new ReducerBuilder<Counter, CounterBuilder>()
110- ..add(CounterActionsNames.increment, increment)
111- ..add(CounterActionsNames.decrement, decrement)).build( );
116+ // This is a reducer builder. Use of ReducerBuilder is not required, however it
117+ // is strongly recommended as it gives you static type checking to make sure
118+ // the payload for action name provided is the same as the expected payload
119+ // for the action provided to your reducer. Calling .build() returns a reducer function
120+ // that can be passed to the store's constructor.
121+ var reducerBuilder = new ReducerBuilder<Counter, CounterBuilder>()
122+ ..add(CounterActionsNames.increment, increment)
123+ ..add(CounterActionsNames.decrement, decrement);
112124
113- // Create a Redux store holding the state of your app.
125+ // Create a redux store holding the state of your app.
114126// Its API contains three getters: stream, state, and actions.
115127var store = new Store<Counter, CounterBuilder, CounterActions>(
116- reducer,
128+ reducerBuilder.build(), // build returns a reducer function
117129 new Counter(),
118130 new CounterActions(),
119131);
@@ -130,121 +142,32 @@ store.actions.decrement(1);
130142// 2
131143```
132144
133- ### Nested Reducers
134-
135- Nested reducers can be built to handle rebuilding built values that are
136- nested within the state tree. This is nice for organization and scoping actions to a specific piece of your application's state.
137-
138- ``` dart
139- // the state model
140- abstract class BaseCounter implements Built<BaseCounter, BaseCounterBuilder> {
141- int get count;
142-
143- // Also a built_value
144- NestedCounter get nestedCounter;
145-
146- // Built value constructor. The factory is returning the default state
147- BaseCounter._();
148- factory BaseCounter() => new _$BaseCounter._(
149- count: 1,
150- nestedCounter: new NestedCounter(),
151- );
152- }
153-
154- // the nested model
155- abstract class NestedCounter implements Built<NestedCounter, NestedCounterBuilder> {
156- int get count;
157-
158- // Built value constructor. The factory is returning the default state
159- NestedCounter._();
160- factory NestedCounter() => new _$NestedCounter._(
161- count: 1,
162- );
163- }
164-
165- // create a nested reducer builder
166- final nestedReducer = new NestedReducerBuilder<BaseCounter, BaseCounterBuilder,
167- NestedCounter, NestedCounterBuilder>(
168- (state) => state.nestedCounter, // maps the app state to the nested state
169- (builder) => builder.nestedCounter, // maps the app builder to the nested builder
170- )..add(NestedCounterActionsNames.increment, _nestedIncrement);
171-
172- // actions registered only rebuild the nested state
173- // notice the state and builder types are of NestedCounter and NestedCounterBuilder
174- _nestedIncrement(NestedCounter state, Action<int> action, NestedCounterBuilder builder) =>
175- builder.count = state.count + action.payload;
176-
177- // now use ReducerBuilder.combineNested to add it to your main reducer
178- var reducer = (new ReducerBuilder<Counter, CounterBuilder>()
179- ..add(CounterActionsNames.increment, increment)
180- ..add(CounterActionsNames.decrement, decrement)
181- ..combineNested(nestedReducer)).build();
182-
183- ```
184-
185- Nested actions can also be used to help organize actions for nested reducers. First define your actions:
186-
187- ``` dart
188- abstract class NestedActions extends ReduxActions {
189- ActionDispatcher<int> increment;
190- ActionDispatcher<int> decrement;
191-
192- // factory to create on instance of the generated implementation of NestedActions
193- NestedActions._();
194- factory NestedActions() => new _$NestedActions();
195- }
196- ```
197-
198- Then add them to your main action class like so:
199-
200- ``` dart
201- abstract class CounterActions extends ReduxActions {
202- ActionDispatcher<int> increment;
203- ActionDispatcher<int> decrement;
204-
205- NestedActions nestedActions;
206-
207- // factory to create on instance of the generated implementation of CounterActions
208- CounterActions._();
209- factory CounterActions() => new _$CounterActions();
210- }
211- ```
212-
213- Check the usage:
214-
215- ``` dart
216- // only print the nested counter's count
217- store.stream.listen((_) => print(store.state.nestedCounter.count));
218-
219- // The only way to mutate the internal state is to dispatch an action.
220- store.actions.nestedActions.increment(1);
221- // 1
222- store.actions.increment(2);
223- // 1
224- ```
225-
226145### Writing middleware
227146
228147``` dart
229- // Define specific actions to be handled by this middleware
230- // A middleware can also listen to and perform side effects on any actions defined elsewhere
148+ // Define specific actions to be handled by this middleware.
149+ // A middleware can also listen to and perform side effects on any actions defined
150+ // elsewhere. It is possible that a middleware will not need any of its own actions
151+ // defined.
231152 abstract class DoubleAction extends ReduxActions {
232- ActionDispatcher<int> increment;
153+ ActionDispatcher<int> get increment;
233154
234155 DoubleAction._();
235156 factory DoubleAction() => new _$DoubleAction();
236157}
237158
238- // This is a middleware builder. Use of MiddlewareBuilder is not required, however
239- // just like ReducerBuilder it is strongly recommended as it gives you static type checking to make sure
240- // the payload for action name provided is the same as the expected payload
241- // for the action provided to your reducer. It will also call next(action) for you
242- // if an action not handled by this middleware is received. Calling .build() returns the
243- // middleware function that can be passed to your store at instantiation.
244- var doubleMiddleware = (new MiddlewareBuilder<Counter, CounterBuilder, CounterActions>()
245- ..add(DoubleActionNames.increment, _doubleIt)).build();
246-
247- _doubleIt(MiddlewareApi<Counter, CounterBuilder, CounterActions> api, ActionHandler next, Action<int> action) {
159+ // This is a middleware builder. Use of MiddlewareBuilder is not required, however
160+ // just like ReducerBuilder it is strongly recommended as it gives you static type checking to make sure
161+ // the payload for action name provided is the same as the expected payload
162+ // for the action provided to your reducer. It will also call next(action) for you
163+ // if an action not handled by this middleware is received. Calling .build() returns the
164+ // middleware function that can be passed to your store at instantiation.
165+ var doubleMiddleware = (new MiddlewareBuilder<Counter, CounterBuilder, CounterActions>()
166+ ..add(DoubleActionNames.increment, _doubleIt)).build();
167+
168+ void _doubleIt(MiddlewareApi<Counter, CounterBuilder, CounterActions> api, ActionHandler next, Action<int> action) {
169+ // doubles the action payload and kicks off a new action to increment the
170+ // store by that amount.
248171 api.actions.increment(action.payload * 2);
249172}
250173```
@@ -301,6 +224,27 @@ NextActionHandler loggingMiddleware(MiddlewareApi<Counter, CounterBuilder, Count
301224 };
302225```
303226
227+ ### Observing state
228+
229+ The store's stream fires with a payload of type StoreChange. This is an object
230+ that contains the action, the previous state, and the next state. If you would
231+ like to set up a stream thats payload is simply the next state, use store.nexState
232+
233+ ``` dart
234+
235+ print(store.state.count);
236+ // 1
237+
238+ store.nextState.listen(print);
239+
240+ store.actions.increment(1);
241+ // 2
242+
243+ store.actions.increment(3);
244+ // 5
245+
246+ ```
247+
304248### Observing substate
305249
306250Streams can easily be accessed to observe any piece of your state tree by passing a mapper the store's
@@ -320,6 +264,25 @@ store.actions.nestedCounter.increment(2);
320264
321265```
322266
267+ In the case of substate streams, the payload is of type SubStateChange. This is an object the previous state, and the next state. If you would
268+ like to set up a stream thats payload is simply the next subState, use store.nexSubstate
269+
270+ ``` dart
271+
272+ print(store.state.count);
273+ // 1
274+
275+ store.nextSubstate((BaseCounter state) => state.count)
276+ .listen(print);
277+
278+ store.actions.increment(1);
279+ // 2
280+
281+ store.actions.increment(3);
282+ // 5
283+
284+ ```
285+
323286[ built_value_blog ] : https://medium.com/dartlang/darts-built-value-for-immutable-object-models-83e2497922d4
324287
325288[ built_value_git ] : https://github.com/google/built_value.dart/
@@ -328,10 +291,18 @@ store.actions.nestedCounter.increment(2);
328291
329292[ redux_docs ] : http://redux.js.org/
330293
331- [ react-dart ] : https://github.com/davidmarne/react_built_redux
332-
333294[ flutter ] : https://github.com/davidmarne/flutter_built_redux
334295
335- [ angular2 ] : https://github.com/davidmarne/angular_built_redux
296+ [ built_redux_thunk ] : https://github.com/davidmarne/built_redux_thunk
297+
298+ [ built_redux_rx ] : https://github.com/davidmarne/built_redux_rx
299+
300+ [ built_redux_repatch ] : https://github.com/davidmarne/built_redux_repatch
336301
337302[ flutter_built_redux ] : https://github.com/davidmarne/flutter_built_redux
303+
304+ [ nesting ] : test/unit/nested_models.dart
305+
306+ [ collection_reducers ] : test/unit/collection_models.dart
307+
308+ [ inheritence ] : test/unit/inheritance_test_models.dart
0 commit comments