Skip to content
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

Use immer within redux-actions #329

Open
mhubig opened this issue Oct 10, 2018 · 3 comments
Open

Use immer within redux-actions #329

mhubig opened this issue Oct 10, 2018 · 3 comments

Comments

@mhubig
Copy link

mhubig commented Oct 10, 2018

Hi together,

I found combining redux-actions with immer to be a very powerful combination to avoid redux boilerplate code. See the example. But I think it would be even more elegant if handleActions would natively use immer to produce the new state.

So this

import produce from 'immer';

const reducer = handleActions(
	{
		[combineActions(
			actionCreators.shoppinglist.fetchDefaultShoppinglist,
			actionCreators.shoppinglist.modifyShoppinglist
		)]: produce((state, { payload }) => {
			state.loading = payload;
		}),
	},
	initialState
);

could be written as:

const reducer = handleActions(
	{
		[combineActions(
			actionCreators.shoppinglist.fetchDefaultShoppinglist,
			actionCreators.shoppinglist.modifyShoppinglist
		)]: ((state, { payload }) => state.loading = payload,
        },
	initialState
);
@vinnymac
Copy link
Contributor

This would be a performance hit and not an insignificant API change to make for this lib in my opinion. Right now it does the same job whether or not you use immer, which means it is more flexible, and remains as fast as the user needs it to be.

If you do want to avoid the boilerplate while still using immer, you can just simply wrap handleActions yourself like so.

import produce from 'immer'
import { handleActions as raHandleActions } from 'redux-actions'

export const handleActions = (actions, state) => raHandleActions(
  Object.keys(actions).reduce((acc, key) => {
    acc[key] = produce(actions[key])

    return acc
  }, {}),
  state
)

Then whenever you need to use it you would just do

import { handleActions } from 'utils/redux-actions'

const reducer = handleActions(
	{
		[combineActions(
			actionCreators.shoppinglist.fetchDefaultShoppinglist,
			actionCreators.shoppinglist.modifyShoppinglist
		)]: ((state, { payload }) => state.loading = payload,
        },
	initialState
);

@raythree
Copy link

I also wrap handleActions as above when I want to use immer. It would be really nice however if you could optionally pass "produce" to handleActions as an option, and have it optionally wrap the returned reducer with it. I'm pretty sure that redux-starter-kit always wraps "createReducer" with immer, and includes it as a dependency. Supporting it in redux-actions like this would be really convenient and not require immer as a dependency or peer dependency:

import { handleActions } from 'redux-actions';
import produce from 'immer';

const mutableReducer = handleActions(reducerMap, defaultState, {produce});

@h0jeZvgoxFepBQ2C
Copy link

that would be pretty nice @raythree

You don't want to submit a PR, don't you? :D
I would love to use this feature too, but not skilled enough to make this PR..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants