Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
11 changes: 7 additions & 4 deletions src/utils/flattenWhenNode.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import isMap from 'lodash/isMap';
import { DEFAULT_NAMESPACE } from '../constants';
import { DEFAULT_NAMESPACE, ACTION_TYPE_DELIMITER } from '../constants';
import ownKeys from './ownKeys';

function get(key, x) {
Expand All @@ -14,9 +14,12 @@ export default predicate =>
partialFlatActionType = ''
) {
function connectNamespace(type) {
return partialFlatActionType
? `${partialFlatActionType}${namespace}${type}`
: type;
if (!partialFlatActionType) return type;
const types = type.toString().split(ACTION_TYPE_DELIMITER);
const partials = partialFlatActionType.split(ACTION_TYPE_DELIMITER);
return []
.concat(...partials.map(p => types.map(t => `${p}${namespace}${t}`)))
.join(ACTION_TYPE_DELIMITER);
}

function connectPrefix(type) {
Expand Down
51 changes: 51 additions & 0 deletions test/handleActions.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -529,3 +529,54 @@ test('works with nested reducerMap and identity handlers', () => {
message: 'hello'
});
});

test('works with combineActions nested', () => {
const {
app: { counter, sameCounter }
} = createActions({
APP: {
COUNTER: undefined,
SAME_COUNTER: undefined
}
});
const { app } = createActions({
APP: {
COUNTER: {
INCREMENT: amount => ({ amount }),
DECREMENT: amount => ({ amount: -amount })
},
SAME_COUNTER: {
INCREMENT: amount => ({ amount }),
DECREMENT: amount => ({ amount: -amount })
}
}
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please check the double usage of createAction in L536 and L542. Shouldn't it be only at L542? counter and sameCounter can be destructured there instead too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes maybe I should rename the actions of L536. In my app I have an API call (which is an action) and I handle SUCCESS, LOADING.. with combineActions.
So I dispatch API_CALL and handle API_CALL_SUCCESS. This is why I have 2 createActions. I tried to reproduce this here but maybe it's confusing. 😐

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, but still couldn't you just remove L536 and do this instead?

const { app } = createActions({
  APP: {
    COUNTER: {
      INCREMENT: amount => ({ amount }),
      DECREMENT: amount => ({ amount: -amount })
    },
    SAME_COUNTER: {
      INCREMENT: amount => ({ amount }),
      DECREMENT: amount => ({ amount: -amount })
    }
  }
});

const { counter, sameCounter } = app

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@timche This doesn't work because of line L558: combineActions(counter, sameCounter). combineActions expect actions, not keys. I can rewrite L536 with:

const app: { counter, sameCounter } = createActions('APP/COUNTER', 'APP/SAME_COUNTER')

..if you prefer.
Or totally change action names and do something like API_CALL and API_CALL_SUCCESS?

I know this is not very clear but the initials dispatched (and combined) actions have to be different than the one nested in the combine.

Copy link
Member

@timche timche May 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, didn't have much time to look into that and try it out myself. I just want it to be changed so the code makes sense. Doesn't matter how and to what, it just must be readable and clear.

Copy link
Member

@timche timche May 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's still not very clear from my perspective because of using undefined in API_CALL_1: { LOADING: undefined }. Why is it defined as undefined? It just doesn't look right and is also not documented.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's totally documented: https://redux-actions.js.org/api-reference/createaction-s#createaction-type-payloadcreator and also used in an example below

SET: undefined // given undefined, the identity function will be used

But if you prefer I can write createAction('API_CALL_1/LOADING'). This way, I use explicitly the / separator which is implicit in the object form.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know that undefined will use the identity function instead, but I'm more concerned about using createActions twice and the first one is just being used for creating action types and the second to create action creators which is overall looks quite confusing imo.

Copy link
Contributor Author

@Kerumen Kerumen May 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know.. As I said, in a real app, the LOADING action would have been created else where (in a middleware for example) so it won't be confusing.

However, this is a simple test ensuring the fix works, maybe we can pass through and improve it later?

I've changed it a few times and I don't have many options left. If you propose me something, I would be happy to include it, I'm currently out of ideas.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think this is too much nitpicking from my side, sorry. After all, this issue is fixed. Thanks!


// NOTE: We should be using combineReducers in production, but this is just a test.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this comment mean, because

  1. combineReducers doesn't exist
  2. if combineActions is meant, it is being used

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just copy-pasted the previous test 🙃

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we can remove it as I don't see that it makes any sense.

const reducer = handleActions(
{
[combineActions(counter, sameCounter)]: {
INCREMENT: ({ counter }, { payload: { amount } }) => ({
counter: counter + amount
}),
DECREMENT: ({ counter }, { payload: { amount } }) => ({
counter: counter + amount
})
}
},
{ counter: 0 }
);

expect(reducer({ counter: 3 }, app.counter.increment(2))).toEqual({
counter: 5
});
expect(reducer({ counter: 10 }, app.counter.decrement(3))).toEqual({
counter: 7
});
expect(reducer({ counter: 3 }, app.sameCounter.increment(2))).toEqual({
counter: 5
});
expect(reducer({ counter: 10 }, app.sameCounter.decrement(3))).toEqual({
counter: 7
});
});