This is a simple/small Redux Store implementation for small angular apps. Use in case you don't want to use the full-blown Redux libraries out there, for the sake of simplicity.
This template code is based and inspired on Ultimate Angular - NGRX Store + Effects Online Training (Free). Highly recommended.
The example below is based on a super simple fictional 'Agenda' app where we can add contacts and to-do tasks.
Copy into your application the following files, from this Gist that form the 'Home-Made Redux Store' class.
- actions.interface.ts
- reducer.interface.ts
- reducers.interface.ts
- home-made-redux-store.ts
Now define your AppState interface and its substates
export interface IContact {
name: string;
email: string;
}
export interface ITask {
description: string;
done: boolean;
}
export interface IAppState {
contacts: IContact[];
tasks: ITask[];
}
export const initialState: IAppState = {
contacts: [
{
name: "Me",
email: "me@example.com"
}
],
tasks: [
{
description: "Start populating this list",
done: false
}
]
}
export enum ActionTypes {
ADD_CONTACT,
ADD_TASK
}
export class TaskAction implements IAction {
public readonly type = ActionTypes.ADD_TASK
constructor (
public payload: ITask
){}
}
export class ContactAction implements IAction {
constructor(
public payload: IContact
) {
}
public readonly type = ActionTypes.ADD_CONTACT;
}
const contactsReducer: IReducer = function (state: IContact[], action: ContactAction) {
switch (action.type) {
case ActionTypes.ADD_CONTACT: {
const contacts = [...state, action.payload];
return contacts;
}
}
return state;
};
const tasksReducer: IReducer = function (state: ITask[], action: TaskAction) {
switch (action.type) {
case ActionTypes.ADD_TASK: {
const tasks = [...state, action.payload];
return tasks;
}
}
return state;
}
export const reducers: IReducers = {
contacts: contactsReducer,
tasks: tasksReducer
};
In this example, the State Service extends the HomeMadeReduxStore
class. Alternatively you could build a wrapper service
that utilizes the HomeMadeReduxStore
class.
@Injectable()
export class AppStateService extends HomeMadeReduxStore<IAppState> {
constructor(
reducers: IReducers = {},
initialState: IAppState = <IAppState>{}
) {
super(reducers, initialState);
}
}
In this example we instanciate the service with our specific state and reducers.
app.module.ts
@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
],
providers: [
{provide: AppStateService, useFactory(){
return new AppStateService(reducers,initialState);
}}
],
bootstrap: [AppComponent]
})
export class AppModule { }
import { TaskAction } from './app-state/actions/task-action';
import { AppStateService } from './app-state/app-state.service';
import { Component } from '@angular/core';
import { ContactAction } from './app-state/actions/contact-action';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'app';
constructor(
private appState: AppStateService
){
console.log('Intial State:', this.appState.value);
this.appState.dispatch(new ContactAction ({
name: "John Doe",
email: "johndoe@example.com"
}));
console.log('Adding contact', this.appState.value);
this.appState.dispatch(new TaskAction ({
description: 'Buy groceries',
done: false
}));
console.log('Added task', this.appState.value);
}
}