-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Description
I think end-developers should be able to opt-out of immer
behavior for createReducer
and createSlice
. There have been some questions raised recently after the 1.0 announcement that people have experienced performance issues when using createSlice
because of immer
.
For most use-cases, I think immer should be enabled. However, there are specific cases where I have needed to tune the performance of a set of reducers and needed to disable immer.
immer definitely provides a ton of value out-of-the-box and I think should be enabled by default. However, I also think this is one area where we can be a little more flexible and allow the option to disable it. createReducer
is still extremely valuable even without immer and I think that is the main reason why I think it should be opt-out.
For createReducer
we could provide an additional parameter that determines if immer is used:
export function createReducer<
S,
CR extends CaseReducers<S, any> = CaseReducers<S, any>
- >(initialState: S, actionsMap: CR): Reducer<S> {
+ >(initialState: S, actionsMap: CR, useImmer: boolean = true): Reducer<S> {
return function(state = initialState, action): S {
+ const caseReducer = actionsMap[action.type];
+ if (!useImmer) {
+ return caseReducer ? caseReducer(state, action) : state;
+ }
// @ts-ignore createNextState() produces an Immutable<Draft<S>> rather
// than an Immutable<S>, and TypeScript cannot find out how to reconcile
// these two types.
return createNextState(state, (draft: Draft<S>) => {
- const caseReducer = actionsMap[action.type];
return caseReducer ? caseReducer(draft, action) : undefined;
});
};
}
Or we could create a separate function
export function createSimpleReducer<
S,
CR extends CaseReducers<S, any> = CaseReducers<S, any>
>(initialState: S, actionsMap: CR, useImmer: boolean = true): Reducer<S> {
return function(state = initialState, action): S {
const caseReducer = actionsMap[action.type];
return caseReducer ? caseReducer(state, action) : state;
};
}
I'm curious of everyone's thoughts. Can anyone else think of other ways to implement this feature?
I also think that createSlice
should provide a property immer
which gets passed to createReducer
.
const slice = createSlice({
name: 'slice',
+ immer: false,
// ...
});
I could see this kind of change requiring some typings work before merging.
I'm willing to do the work to get a PR up for this, but I wanted to make sure it was something that the maintainers agree would be useful.