npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

redux-typed-kit

v0.0.4

Published

Powerful extensitions for building class-based Redux architecture powered by TypeScript.

Downloads

74

Readme

redux-typed-kit

Powerful extensitions for building class-based Redux architecture powered by TypeScript.

Example of using redux-typed-kit-example

Installation

  1. Run

    npm i redux-typed-kit
  2. Configure your Babel to support class properties and decorators inside .babelrc

    "plugins": [
         ["@babel/plugin-proposal-decorators", { "legacy": true }],
         ["@babel/plugin-proposal-class-properties", { "loose": true }]
    ]
  3. If you use TypeScript you should configure it inside tsconfig.json

    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
  4. If you use React you also should install reflect-metadata

    npm i reflect-metadata

    and then import it at the top of the entry file

    import 'reflect-metadata';

Quick start

Let's create a simple Redux-architecture to fetch users from server and display them. We'll also take care about possible network (and others) errors.

States

Let's describe users state

import { State } from 'redux-typed-kit';

export default class UsersState extends State {
  public users: Array<User> = [];
  public filter: UsersFilter = new UsersFilter();
  public isLoading: boolean = false;
  public error: ApiError;
}

AppState should include all other states

import { State } from 'redux-typed-kit';

export default class AppState extends State {
  public usersState: UsersState;
}

RebuildState

The State class has the Rebuild method, which is needed to create an instance of the State class, based on the parent instance, but with some changes. It's very helpful to use in any reducers, especially when you need to save the type of your state class.

state.rebuild(x => {
  x.isLoading = true;
});

Actions

Let's create three actions for fetching users. Action to start fetching, action in case of success and in case of error.

import { Action } from 'redux-typed-kit';

export class FetchUsersAction extends Action {
  constructor(public filter: FetchUsersFilter) {
    super();
  }
}

export class FetchUsersSuccessAction extends Action {
  constructor(public response: FetchUsersResponse) {
    super();
  }
}

export class FetchUsersFailureAction extends Action {
  constructor(public error: ApiError) {
    super();
  }
}

Reducers

Let's create users reducer. Every reducer must have two basic things: initial state and name. This name will be used to configure the global app state.

import { Reducer, ActionDecorator as Action } from 'redux-typed-kit';
import UsersState from '../models/states/users-state';
import { FetchUsersAction, FetchUsersSuccessAction, FetchUsersFailureAction } from '../actions/fetch-users-action';

export default class UsersReducer extends Reducer<UsersState> {
  initialState = new UsersState();
  name = 'usersState';

  @Action
  fetchUsers(state: UsersState, action: FetchUsersAction): UsersState {
    return state.rebuild(x => {
      x.isLoading = !action.isBackgroud;
    });
  }

  @Action
  fetchUsersSuccess(state: UsersState, action: FetchUsersSuccessAction): UsersState {
    return state.rebuild(x => {
      x.users = action.response.users;
      x.isLoading = false;
    });
  }

  @Action
  fetchUsersFailure(state: UsersState, action: FetchUsersFailureAction): UsersState {
    return state.rebuild(x => {
      x.error = action.error;
      x.isLoading = false;
    });
  }
}

CombinedReducer

CombinedReducer combines several reducers into one complex reducer and state object just like combineReducers function does.

import { CombinedReducer } from 'redux-typed-kit';
export default new CombinedReducer('complexState', new SimpleReducer(), new AnotherSimpleReducer());

RootReducer

RootReducer combines others reducers (including CombinedReducer) and used by store.

import { RootReducer } from 'redux-typed-kit';
import UsersReducer from './users-reducer';

const rootReducer = new RootReducer(
  new UsersReducer() /*, new CombinedReducer(...), new AnotherReducer()*/
);
export default rootReducer;

Middlewares

We will use middleware to make a request to the server, process the response, and send data to the reducers.

import { PostMiddlewareHandler, Middleware, Store } from 'redux-typed-kit';
import AppState from '../models/states/app-state';
import { FetchUsersAction, FetchUsersSuccessAction, FetchUsersFailureAction, FetchUsersCancelAction } from '../actions/fetch-users-action';

export default class UsersMiddleware extends Middleware<AppState> {
    @PostMiddlewareHandler
    async fetchUsers(store: Store<AppState>, action: FetchUsersAction) {
        const result = await api.fetchUsers(action.filter);
        if (result.error == null) {
            store.dispatch(new FetchUsersSuccessAction(result.response));
        } else {
            store.dispatch(new FetchUsersFailureAction(result.error));
        }
    }
}

PreMiddlewareHandler

PreMiddlewareHandler decorator is used when we need to catch any dispached actions before they get to the reducers. So we can get state from Store before any changes are applied inside the reducers.

PostMiddlewareHandler

PostMiddlewareHandler decorator works exactly the opposite. All reducers already handled the action and changed the state.

Probably the best example I can give you is middlware for logging all actions and state's changes.

import { PostMiddlewareHandler, PreMiddlewareHandler, Middleware, Store } from 'redux-typed-kit';

export default class LoggerMiddleware extends Middleware<AppState> {
    @PreMiddlewareHandler
    preLog(store: Store<AppState>, action: any) {
        console.log('PRE', action, JSON.parse(JSON.stringify(store.getState())));
    }

    @PostMiddlewareHandler
    postLog(store: Store<AppState>, action: any) {
        console.log('POST', action, JSON.parse(JSON.stringify(store.getState())));
    }
}

Store

Store is a combination of RootReducer and Middlewares that create a final state object.

import { Store } from 'vue-redux-ts';
import AppState from '../models/states/app-state';
import rootReducer from '../reducers/root-reducer';
import UsersMiddleware from '../middlewares/users-middleware';

const store = new Store<AppState>(rootReducer, new UsersMiddleware());
export default store.init();

Documentation coming soon...