Skip to content

Instantly share code, notes, and snippets.

@romgrk
Last active October 28, 2024 19:06
Show Gist options
  • Save romgrk/bb16d7b8d3827481d04eb535e8d1bc74 to your computer and use it in GitHub Desktop.
Save romgrk/bb16d7b8d3827481d04eb535e8d1bc74 to your computer and use it in GitHub Desktop.
redux-toolkit reducers without immer
import { AnyAction, Slice } from '@reduxjs/toolkit'
/* The redux-toolkit maintainers refuse to add a way to disable immer.js for
* specific reducers, therefore we need to create an escape hatch by ourselves.
* Immer.js needs to be disabled in certain cases for performance reasons.
* Link: https://github.com/reduxjs/redux-toolkit/issues/242
*/
/** Add reducers without immer.js to a redux-toolkit slice */
export function addRawReducers<S>(
slice: Slice<S>,
reducers: Record<string, ((state: S, action: AnyAction) => S)>
) {
const originalReducer = slice.reducer
const actionMap =
Object.fromEntries(
Object.entries(reducers)
.map(([name, fn]) => [`${slice.name}/${name}`, fn]))
slice.reducer = (state: S | undefined, action: AnyAction) => {
const fn = actionMap[action.type]
if (fn)
return fn(state!, action)
return originalReducer(state, action)
}
const actionCreators =
Object.fromEntries(
Object.entries(reducers)
.map(([name]) =>
[name, (payload: any) => ({ type: `${slice.name}/${name}`, payload })]))
return actionCreators
}
const slice = createSlice({
name: 'arithmetic',
initialState: { value: 0 },
reducers: {
sub: (state, action) => {
state.value -= 1
},
},
})
const { add } = addRawReducers(slice, {
add: (state, action) => {
return { ...state, value: state.value + 1 }
}
})
@TucsonLiu
Copy link

Thank you. You've done me a great favor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment