gajus / redux-immutable-examples

A complete application showing use of redux-immutable.
102 stars 19 forks source link

A way to reduce actions boilerplate #2

Open IlyaSemenov opened 8 years ago

IlyaSemenov commented 8 years ago

Here's the current actions boilerplate:

taskAdd = (name) => ({
    name: 'TASK_ADD',
    data: {
        name
    }
});

taskDone = (id) => ({
    name: 'TASK_DONE',
    data: {
        id
    }
});

It suffers from these problems:

1) Repetitive typing where you repeat name and data for each action and then also repeat the list of parameters, twice for each action. 2) Action names are not defined as reusable/importable constants (therefore you can't enforce compile-time checks on them). 3) (Minor) For some reason you're not using const but instead let the variables at top of the file. I guess it's some legacy/habit issue?

Have you given any thought on these problems before? I like the CRC/CCA approach in general but applying it directly means sacrificing the above. For example, with redux-actions I can:

// Identity action creator, no boilerplate at all, clean and DRY.
export const chatMessageSent = createAction('CHAT_MESSAGE_SENT');

and then (in a redux saga):

import {chatMessageSent} from '.../actions'

yield takeEvery(chatMessageSent.toString(), function* ({payload: {contact, text}}) {
    // ...
});

and I get no headache about possible typos in the action names.

Of course I can come up with a poor man ad-hoc shortcut, something like:

function createAction(name) {
    const action = (data, metadata) => ({name, data, metadata});
    action.name = name;
    return action;
}
...
chatMessageSent = createAction('CHAT_MESSAGE_SENT');
...
yield takeEvery(chatMessageSent.name, function* ({data: {contact, text}}) {
    // ...
});

but a proper well-thought library when you still can override the action creator logic, specify list of fields etc. would be better.

And then again, in redux-immutable you need to use these ALL_CAPS constants (which you can't import!) as the key names in reducers, while in redux-actions they provide a handy shortcut with compile-time check (something your combineReducers could also benefit from):

const reducer = handleActions({
    [selectContact]: (state, {payload: {id}}) => ({
        ...state,
        selectedId: id
    }),

I know this is not a proper ticket and more of a rant, but anyway. šŸ™ƒ