-
Notifications
You must be signed in to change notification settings - Fork 300
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
Allow nested reducer map in handleActions #218
Allow nested reducer map in handleActions #218
Conversation
Can we get the build passing before review? Thanks @zcei. |
b4d1421
to
a8c6add
Compare
@yangmillstheory oops, Node 4 has no |
Thanks. Can we include some README documentation? |
Thanks. I will get to this; but to set expectations, I'm usually busy with other things during weeknights. It might be the case that the earliest that I can review this is this weekend. |
src/__tests__/handleActions-test.js
Outdated
next: ({ counter, message }, { payload }) => ({ | ||
counter, | ||
message: `${message}---${payload.message}` | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a throw
handler and a test for that code path?
src/handleActions.js
Outdated
|
||
export default function handleActions(handlers, defaultState) { | ||
invariant( | ||
isPlainObject(handlers), | ||
'Expected handlers to be an plain object.' | ||
); | ||
const reducers = ownKeys(handlers).map(type => | ||
const flatHandlers = flattenReducerMap(handlers); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we call this flattenedReducerMap
?
src/namespaceActions.js
Outdated
|
||
const defaultNamespace = '/'; | ||
|
||
function flattenActionMap( | ||
actionMap, | ||
function hasGeneratorInterface(handler) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe put this in a separate module, like ownKeys
, camelCase
, and arrayToObject
?
src/namespaceActions.js
Outdated
function hasGeneratorInterface(handler) { | ||
const generatorFnNames = ['next', 'throw']; | ||
const keys = Object.getOwnPropertyNames(handler); | ||
const onlyInterfaceFns = keys.every((fnName) => includes(generatorFnNames, fnName)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can just say, using https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every,
const hasOnlyInterfaceNames = Object.getOwnPropertyNames(handler).every(ownPropertyName => ownPropertyName === 'next' || ownPropertyName === 'throw)
README.md
Outdated
@@ -207,6 +207,8 @@ import { handleActions } from 'redux-actions'; | |||
|
|||
Creates multiple reducers using `handleAction()` and combines them into a single reducer that handles multiple actions. Accepts a map where the keys are passed as the first parameter to `handleAction()` (the action type), and the values are passed as the second parameter (either a reducer or reducer map). The map must not be empty. | |||
|
|||
If `reducerMap` has a recursive structure, its leaves are used as reducers, and the action type for each leaf is the path to that leaf. If a node's only children are `next()` and `throw()`, the node will be treated as a reducer. | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For leaves I think we should also support:
- array form
[payload, meta]
- function form (this will be used as the reducer)
undefined
ornull
(reducer just returns previous state)
This will keep compatibility with the previous API.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
array form
[payload, meta]
Isn't this exclusively for action creators? 🤔
I think undefined
, null
& 'fn' as leaves are all possible, as they're just passed to handleAction
.
I'll add tests for this!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, you're right about the action creators. Thanks for correcting.
src/__tests__/handleActions-test.js
Outdated
counter, | ||
message: `${message}---${payload.message}` | ||
}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, we should implement and add tests for https://github.com/acdlite/redux-actions/pull/218/files#r125166038.
src/namespaceActions.js
Outdated
actionMap, | ||
function hasGeneratorInterface(handler) { | ||
const generatorFnNames = ['next', 'throw']; | ||
const keys = Object.getOwnPropertyNames(handler); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use ownKeys
?
src/namespaceActions.js
Outdated
return partialFlatMap; | ||
}; | ||
|
||
const flattenActionMap = flattenBy((node) => isPlainObject(node)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we just pass in the predicate?
flattenBy(isPlainObject)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, just wanted to keep it consistent with the line below
src/namespaceActions.js
Outdated
}; | ||
|
||
const flattenActionMap = flattenBy((node) => isPlainObject(node)); | ||
const flattenReducerMap = flattenBy((node) => isPlainObject(node) && !hasGeneratorInterface(node)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See https://github.com/acdlite/redux-actions/pull/218/files#r125166038, I think this will have to change.
This is great, thanks! I should have started a review to not e-mail spam you, sorry. I have some comments and questions; let me know what you think. |
40cb54d
to
75e51aa
Compare
Thanks @zcei, this looks good |
src/handleActions.js
Outdated
@@ -3,16 +3,18 @@ import reduceReducers from 'reduce-reducers'; | |||
import invariant from 'invariant'; | |||
import handleAction from './handleAction'; | |||
import ownKeys from './ownKeys'; | |||
import { flattenReducerMap } from './namespaceActions'; | |||
|
|||
export default function handleActions(handlers, defaultState) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if this should now take a namespace character like createActions
does...thoughts? If so, it should probably be documented and tested.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was thinking about it earlier, but left it out, as it made readability worse, as you now have to objects after each other and on a quick glimpse you might think { namespace }
would be default state.
Just added tests for it, seems to work "out of the box" by just passing the (maybe undefined
) namespace
property through.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm guessing most people wouldn't even want to use the custom namespace property anyway. We can add later if requested.
src/namespaceActions.js
Outdated
@@ -32,7 +32,9 @@ const flattenWhenNode = predicate => function flatten( | |||
}; | |||
|
|||
const flattenActionMap = flattenWhenNode(isPlainObject); | |||
const flattenReducerMap = flattenWhenNode(node => isPlainObject(node) && !hasGeneratorInterface(node)); | |||
const flattenReducerMap = flattenWhenNode( | |||
node => isPlainObject(node) && !hasGeneratorInterface(node) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yangmillstheory the renaming to flattenWhenNode
broke the tests because line was too long.
Is this notation fine, or do you want to have only the expression in separate line?
Looks good to me 👍🏿
On Sun, Jul 2, 2017 at 1:30 PM Stephan Schneider ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In src/namespaceActions.js
<#218 (comment)>:
> @@ -32,7 +32,9 @@ const flattenWhenNode = predicate => function flatten(
};
const flattenActionMap = flattenWhenNode(isPlainObject);
-const flattenReducerMap = flattenWhenNode(node => isPlainObject(node) && !hasGeneratorInterface(node));
+const flattenReducerMap = flattenWhenNode(
+ node => isPlainObject(node) && !hasGeneratorInterface(node)
@yangmillstheory <https://github.com/yangmillstheory> the renaming to
flattenWhenNode broke the tests because line was too long.
Is this notation fine, or do you want to have only the expression in
separate line?
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#218 (review)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ACmkd9a5qsE7ua0gdTqiYM1TCttibqkeks5sJ_30gaJpZM4OEfTX>
.
--
Victor Alvarez
|
I'm at the beach 🏖, will merge this when I get back home later. Thanks @zcei! |
|
Fixes #215
Introduces
flattenReducerMap
with same behavior asflattenActionMap
- except a guard, so that generator alike{ next, throw }
objects are treated as a reducer.As a side-note I would recommend to distinguish between
reducerMap
for a single reducer (the generator alike interface inhandleAction
) and a namespacedreducerMap
inhandleActions
.Can't come up with something better than
reducerObject
/namedReducers
myself though.