createSlice plugin for NgRX
npm install ngrx-slicengrx-slice is a plugin that intends to provide the same functionalities
that Redux Toolkit createSlice provides. It is meant to be
opinionated.
``shell`
npm install ngrx-slice
`shell`
yarn add ngrx-slice
ngrx-slice has immer as its peerDependencies so go ahead and install it:
`shell`
npm install immer
`shell`
yarn add immer
Visit NgRX Slice Documentations
NgRX has always been _coupled_ with boilerplate. Even with the new Creator APIs, the amount of boilerplate
needed to set up a single feature state is still a lot (to remember). To fully utilize NgRX for a Feature State,
you'd need:
- Actions (createAction)createSelector
- Selectors ( and createFeatureSelector)createReducer
- Reducer ()
Regardless of whether you separate these entities into different files, or keep them in the same file, the cognitive
overhead is still there. ngrx-slice solves this issue for me.
Here's an example of a CounterState using createAction, createSelector, createFeatureSelector,createReducer
and
`ts
// Actions
const increment = createAction("[Counter] increment");
const decrement = createAction("[Counter] decrement");
const double = createAction("[Counter] double");
const multiplyBy = createAction(
"[Counter] multiplyBy",
props<{ multiplier: number }>()
);
const multiplyBySuccess = createAction(
"[Counter] multiplyBy success",
props<{ value: number }>()
);
// Reducer
interface CounterState {
value: number;
increment: number;
decrement: number;
}
const initialState: CounterState = {
value: 0,
increment: 0,
decrement: 0,
};
const counterReducer = createReducer(
initialState,
on(increment, (state) => ({
...state,
value: state.value + 1,
increment: state.increment + 1,
})),
on(decrement, (state) => ({
...state,
value: state.value - 1,
decrement: state.decrement + 1,
})),
on(multiplyBySuccess, (state, action) => ({ ...state, value: action.value })),
on(double, (state) => ({ ...state, value: state.value * 2 }))
);
// Selectors
const selectCounterState = createFeatureSelector("counter");
const selectValue = createSelector(selectCounterState, (state) => state.value);
const selectIncrement = createSelector(
selectCounterState,
(state) => state.increment
);
const selectDecrement = createSelector(
selectCounterState,
(state) => state.decrement
);
`
> There is an Effect that will handle multiplyBy action but this will be the same for ngrx-slice as well.
Or you can have everything in a Slice
`ts
import { createSlice } from 'ngrx-slice';
export interface CounterState {
value: number;
incrementCount: number;
decrementCount: number;
}
export const initialState: CounterState = {
decrementCount: 0,
incrementCount: 0,
value: 0,
};
export const {
actions: CounterActions,
selectors: CounterSelectors,
...CounterFeature
} = createSlice({
name: 'counter',
initialState,
reducers: {
increment: (state) => {
state.value++;
state.incrementCount++;
},
decrement: (state) => {
state.value--;
state.decrementCount++;
},
},
});
``
Contributions welcome