ngrx-slice
is a plugin that intends to provide the same functionalities
that Redux Toolkit createSlice provides. It is meant to be opinionated.
npm install ngrx-slice
yarn add ngrx-slice
ngrx-slice
has ngrx-immer
and immer
as its peerDependencies
so go ahead and install those:
npm install ngrx-immer immer
yarn add ngrx-immer immer
Here's one command for all three:
npm install ngrx-slice ngrx-immer immer
yarn add ngrx-slice ngrx-immer 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
) - Selectors (
createSelector
andcreateFeatureSelector
) - Reducer (
createReducer
)
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
,
and createReducer
// 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 handlemultiplyBy
action but this will be the same forngrx-slice
as well.
Or you can have everything in a Slice
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