-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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.