@@ -73,10 +73,14 @@ programming.
73
73
__ Summary__
74
74
75
75
- There are no adapters. ` redux-most ` is only intended to be used with ` Most ` .
76
+ - ` redux-most ` offers 2 separate APIs: a ` redux-observable ` -like API, where Epics
77
+ get passed an action stream & a store middleware object containing ` dispatch ` & ` getState `
78
+ methods, and a stricter, more declarative API, where Epics get passed an action stream & a state stream.
76
79
- ` combineEpics ` takes in an array of epics instead of multiple arguments.
77
80
- Standard ` Most ` streams are used instead of a custom Observable extension.
78
81
- ` select ` and ` selectArray ` are available instead of the variadic ` ofType ` .
79
82
83
+
80
84
__ Further Elaboration:__
81
85
82
86
As the name implies, ` redux-most ` does not offer adapters for use with other reactive
@@ -87,8 +91,23 @@ JavaScript ecosystem right now, and `Most 2.0` will be even better, as it will f
87
91
auto-curried API like ` lodash/fp ` and ` ramda ` , but for working with streams instead of arrays.
88
92
For a preview of what's to come, check out what's going on [ here] ( https://github.com/mostjs/core ) .
89
93
90
- Whereas ` comebineEpics ` is variadic in ` redux-observable ` , it's unary in ` redux-most ` . It takes in
91
- only one argument, an array of epics, instead of individual epics getting passed in as separate
94
+ Initially, ` redux-most ` offered the same API as ` redux-observable ` , where Epics received an action
95
+ stream & a store middleware object containing ` dispatch ` & ` getState ` methods. However, it now offers
96
+ both that API and another stricter, more declarative API which eliminates the use of ` dispatch ` &
97
+ ` getState ` . The reason for this is that I rarely found myself using the imperative ` dispatch `
98
+ method. It's not really needed, because you can use ` switch ` , ` merge ` , ` mergeArray ` , etc. to send
99
+ multiple actions through your outgoing stream. This is nice, because it allows you to stay locked into
100
+ the declarative programming style the entire time.
101
+
102
+ However, using ` getState ` was still required in epics that needed access to the current state. I
103
+ wanted a nice, convenient way to access the current state, just like I had for dispatching actions.
104
+ So, I created an alternate API where Epics receive a stream of state changes rather than the
105
+ ` { dispatch, getState } ` object. This state stream, combined with the new ` withState ` utility function,
106
+ let's you use streams for both dispatching actions & accessing the current state, allowing you to stay
107
+ focused & in the zone (the reactive programming mindset).
108
+
109
+ Moving on, whereas ` comebineEpics ` is variadic in ` redux-observable ` , it's unary in ` redux-most ` . It
110
+ takes in only one argument, an array of epics, instead of individual epics getting passed in as separate
92
111
arguments.
93
112
94
113
As for streams, I chose not to extend the ` Observable ` type with a custom ` ActionsObservable `
@@ -105,7 +124,7 @@ practice in functional programming to prefer a known number of arguments over a
105
124
of arguments. Therefore, ` select ` is used when we want to filter by a single action type, and
106
125
` selectArray ` is used when we want to filter by multiple action types (via an array) simultaneously.
107
126
108
- Additionally, to better align with the ` Most ` API, and because these fucntions take a known number
127
+ Additionally, to better align with the ` Most ` API, and because these functions take a known number
109
128
of arguments, ` select ` & ` selectArray ` are curried, which allows them to be used in either a
110
129
fluent style or a more functional style which enables the use of further currying, partial
111
130
application, & functional composition.
@@ -161,11 +180,13 @@ const someOtherEpic = pipe(
161
180
## API Reference
162
181
163
182
- [ createEpicMiddleware] ( https://github.com/joshburgess/redux-most#createepicmiddleware-rootepic )
183
+ - [ createStateStreamEnhancer] ( https://github.com/joshburgess/redux-most#createstatestreamenhancer-epicmiddleware )
164
184
- [ combineEpics] ( https://github.com/joshburgess/redux-most#combineepics-epics )
165
185
- [ EpicMiddleware] ( https://github.com/joshburgess/redux-most#epicmiddleware )
166
186
- [ replaceEpic] ( https://github.com/joshburgess/redux-most#replaceEpic )
167
187
- [ select] ( https://github.com/joshburgess/redux-most#select-actiontype-stream )
168
188
- [ selectArray] ( https://github.com/joshburgess/redux-most#selectArray-actiontypes-stream )
189
+ - [ withState] ( https://github.com/joshburgess/redux-most#withstate-statestream-actionstream )
169
190
170
191
---
171
192
@@ -204,6 +225,44 @@ export default function configureStore() {
204
225
205
226
---
206
227
228
+ ### ` createStateStreamEnhancer (epicMiddleware) `
229
+
230
+ ` createStateStreamEnhancer ` is used to access ` redux-most ` 's alternate API, which passes
231
+ ` Epics ` a state stream (Ex: ` state$ ` ) instead of the ` { dispatch, getState } ` store
232
+ ` MiddlewareAPI ` object. You must provide an instance of the ` EpicMiddleware ` , and the
233
+ resulting function must be applied AFTER using ` redux ` 's ` applyMiddleware ` if also using
234
+ other middleware.
235
+
236
+ __ Arguments__
237
+
238
+ 1 . ` rootEpic ` _ (` Epic ` )_ : The root Epic.
239
+
240
+ __ Returns__
241
+
242
+ _ (` MiddlewareAPI ` )_ : An enhanced instance of the ` redux-most ` middleware, exposing a stream
243
+ of state change values.
244
+
245
+ __ Example__
246
+ ``` js
247
+ import { createStore , applyMiddleware } from ' redux'
248
+ import {
249
+ createEpicMiddleware ,
250
+ createStateStreamEnhancer ,
251
+ } from ' redux-most'
252
+ import rootEpic from ' ../epics'
253
+
254
+ const epicMiddleware = createEpicMiddleware (rootEpic)
255
+ const middleware = [... ] // other middleware here
256
+ const storeEnhancers = compose (
257
+ createStateStreamEnhancer (epicMiddleware),
258
+ applyMiddleware (... middleware)
259
+ )
260
+
261
+ const store = createStore (rootReducer, storeEnhancers)
262
+ ```
263
+
264
+ ---
265
+
207
266
### ` combineEpics (epicsArray) `
208
267
209
268
` combineEpics ` , as the name suggests, allows you to pass in an array of epics and combine them into a single one.
@@ -298,6 +357,11 @@ __Arguments__
298
357
1 . ` actionType ` _ (` string ` )_ : The type of action to filter by.
299
358
2 . ` stream ` _ (` Stream ` )_ : The stream of actions you are filtering. Ex: ` actions$ ` .
300
359
360
+ __ Returns__
361
+
362
+ _ (Stream)_ : A new, filtered stream holding only the actions corresponding to the action
363
+ type passed to ` select ` .
364
+
301
365
The ` select ` operator is curried, allowing you to use a fluent or functional style.
302
366
303
367
__ Examples__
@@ -369,6 +433,11 @@ __Arguments__
369
433
1 . ` actionTypes ` _ (` string[] ` )_ : An array of action types to filter by.
370
434
2 . ` stream ` _ (` Stream ` )_ : The stream of actions you are filtering. Ex: ` actions$ ` .
371
435
436
+ __ Returns__
437
+
438
+ _ (Stream)_ : A new, filtered stream holding only the actions corresponding to the action
439
+ types passed to ` selectArray ` .
440
+
372
441
The ` selectArray ` operator is curried, allowing you to use a fluent or functional style.
373
442
374
443
__ Examples__
@@ -447,3 +516,52 @@ const clear = compose(
447
516
448
517
export default clear
449
518
```
519
+ ---
520
+
521
+ ### ` withState (stateStream, actionStream) `
522
+
523
+ A utility function for use with ` redux-most ` 's optional state stream API. This
524
+ provides a convenient way to ` sample ` the latest state change value. Note:
525
+ accessing the alternate API requires using ` createStateStreamEnhancer ` .
526
+
527
+ __ Arguments__
528
+
529
+ 1 . ` stateStream ` _ (` Stream ` )_ : The state stream provided by ` redux-most ` 's alternate API.
530
+ 2 . ` actionStream ` _ (` Stream ` )_ : The filtered stream of action events used to trigger
531
+ sampling of the latest state. (Ex: ` actions$ ` ).
532
+
533
+ __ Returns__
534
+
535
+ _ (` [state, action] ` )_ : An Array of length 2 (or Tuple) containing the latest
536
+ state value at index 0 and the latest action of the filtered action stream at index 1.
537
+
538
+ ` withState ` is curried, allowing you to pass in the state stream & action stream
539
+ together, at the same time, or separately, delaying passing in the action stream.
540
+ This provides the user extra flexibility, allowing it to easily be used within
541
+ functional composition pipelines.
542
+
543
+ __ Examples__
544
+ ``` js
545
+ import { select , withState } from ' redux-most'
546
+ import { curriedMap as map } from ' ../utils'
547
+ import compose from ' ramda/src/compose'
548
+
549
+ const accessStateFromArray = ([state , action ]) => ({
550
+ type: ' ACCESS_STATE' ,
551
+ payload: {
552
+ latestState: state,
553
+ accessedByAction: action,
554
+ },
555
+ })
556
+
557
+ // dispatch { type: 'STATE_STREAM_TEST' } in Redux DevTools to test
558
+ const stateStreamTest = (action$ , state$ ) => compose (
559
+ map (accessStateFromArray),
560
+ withState (state$),
561
+ select (' STATE_STREAM_TEST' )
562
+ )(action$)
563
+
564
+ export default stateStreamTest
565
+ ```
566
+
567
+ ---
0 commit comments