Skip to content

Framework-agnostic and class-based typed reducers

License

Notifications You must be signed in to change notification settings

jwsims/typed-reducer

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

17 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

typed-reducer

This library is a framework-agnostic attempt to create typed reducers with Typescript following a class-based approach. Due to this, it plays particularly nicely with @ngrx.

Install

npm i typed-reducer --save 

Usage

import { createReducer, Action } from 'typed-reducer';

const ACTION_TYPE = 'ACTION_TYPE';

// define an action
class MyAction {
    public type = ACTION_TYPE;
    constructor(public payload: string) {}
}

// create a class, each method is a branch of what we would normally do with a switch statement
export class Reducer {
    @Action
    public someMethod(state: string[], action: MyAction): State {
        return [ ...state, action.payload];
    }
}

export const reducer = createReducer(Reducer);

Full example

import { createReducer, Action } from 'typed-reducer';
import { CreateTodoAction, MarkTodoDoneAction, ArchiveTodoAction } from './todo.actions';
import { createTodo } from './create-todo';

export class TodoReducer {
    @Action
    public createTodo(state: Todo[], action: CreateTodoAction): Todo[] {
        return [ ...state, createTodo(action.payload)];
    }

    @Action
    public markDone(state: Todo[], action: MarkTodoDoneAction): Todo[] {
        return state.map(todo => {
            return todo.id === action.payload ? { ...todo, done: true } : todo
        });
    }

    @Action
    public archiveTodo(state: Todo[], action: ArchiveTodoAction): Todo[] {
        return state.filter(todo => todo.id !== action.payload);
    }
}

export const reducer = createReducer(TodoReducer);

Use with Ngrx and AOT

import { reducer } from './todos.reducer.ts';

// initial state of the store's tree
const initialState = {
  todos: []
};

// create your store tree
export const rootReducer = (
  state: AppState = initialState,
  action: Action
) => {
  return {
    todos: reducer(state.todos, action),
    // here go your other reducers
  };
};

// export a factory to be AOT compliant
export function reducerFactory() {
  return rootReducer;
};

// let's pass the factory function to StoreModule
@NgModule({
  // module's configuration ...
  imports: [
    StoreModule.forRoot(undefined, { reducerFactory })
  ]
})
export class AppModule { }

Options

Freeze

In order to prevent errors related to mutating the state, you can pass the option freeze, so that the state will be frozen using Object.freeze. Do this only in dev mode.

const options = { freeze: true };
export const todos = createReducer(TodoReducer, options);

Log

It is possible to log every action by setting the property log to true. This has been inspired by ngrx-store-logger. Do this only in dev mode.

Logging

const options = { log: true };
export const todos = createReducer(TodoReducer, options);

About

Framework-agnostic and class-based typed reducers

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • TypeScript 82.2%
  • JavaScript 10.4%
  • HTML 6.9%
  • CSS 0.5%