Skip to main content

withRedux()

// DEPRECATED
import { withRedux } from '@angular-architects/ngrx-toolkit';

// Use `@ngrx/signals/events` instead

withRedux() brings back the Redux pattern into the Signal Store.

It can be combined with any other extension of the Signal Store.

warning

Deprecation

Please note, @ngrx/signals/events was released as experimental in @ngrx/signals/ v19.2.

If you use withRedux, you should transition to using the official @ngrx/signals/events features.

There is also a Redux Connector available, which is a separate package and has a dependency to @ngrx/store.

Example:

import { withRedux } from '@angular-architects/ngrx-toolkit';

export const FlightStore = signalStore(
{ providedIn: 'root' },
withState({ flights: [] as Flight[] }),
withRedux({
actions: {
public: {
load: payload<{ from: string; to: string }>(),
},
private: {
loaded: payload<{ flights: Flight[] }>(),
},
},
reducer(actions, on) {
on(actions.loaded, (state, { flights }) => {
updateState(state, 'flights loaded', { flights });
});
},
effects(actions, create) {
const httpClient = inject(HttpClient);
return {
load$: create(actions.load).pipe(
switchMap(({ from, to }) =>
httpClient.get<Flight[]>('https://demo.angulararchitects.io/api/flight', {
params: new HttpParams().set('from', from).set('to', to),
})
),
tap((flights) => actions.loaded({ flights }))
),
};
},
})
);

Extracting actions, reducer and effects into separate files

import { createReducer } from '@angular-architects/ngrx-toolkit';
import { createEffects } from '@angular-architects/ngrx-toolkit';

createReducer and createEffects allow you to extract the reducer and effects into separate files.

There is no need for a createActions function, because the actions are just an object literal.

Example:

import { withRedux, createReducer, createEffects } from '@angular-architects/ngrx-toolkit';

interface FlightState {
flights: Flight[];
effect1: boolean;
effect2: boolean;
}

const initialState: FlightState = {
flights: [],
effect1: false,
effect2: false,
};

// this can be in a separate file
const actions = {
init: noPayload,
updateEffect1: payload<{ value: boolean }>(),
updateEffect2: payload<{ value: boolean }>(),
};

// this can be in a separate file
const reducer = createReducer<FlightState, typeof actions>((actions, on) => {
on(actions.updateEffect1, (state, { value }) => {
updateState(state, 'update effect 1', { effect1: value });
});

on(actions.updateEffect2, (state, { value }) => {
updateState(state, 'update effect 2', { effect2: value });
});
});

// this can be in a separate file
const effects = createEffects(actions, (actions, create) => {
return {
init1$: create(actions.init).pipe(map(() => actions.updateEffect1({ value: true }))),
init2$: create(actions.init).pipe(map(() => actions.updateEffect2({ value: true }))),
};
});

signalStore(
withState(initialState),
withRedux({
actions,
effects,
reducer,
})
);

Configuring the Redux Devtools Extension

import { provideDevtoolsConfig } from '@angular-architects/ngrx-toolkit';

The provideDevtoolsConfig function allows you to configure the Redux DevTools integration for your NgRx SignalStore. This function is essential for setting up the DevTools with custom options. The function only needs to be called once in your appConfig or AppModule.

To use provideDevtoolsConfig, you need to import it and call it in your providers array.

Here is an example of how to use it with the standalone api:

// app.config.ts
import { ApplicationConfig } from '@angular/core';
import { provideDevtoolsConfig } from '@angular-architects/ngrx-toolkit';

export const appConfig: ApplicationConfig = {
providers: [
provideDevtoolsConfig({
name: 'MyApp',
}),
],
};

// main.ts
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app/app.component';
import { appConfig } from './app/app.config.ts';

await bootstrapApplication(AppComponent, appConfig);

Additional Information

For more details on the available options and their usage, refer to the Redux DevTools Extension documentation.