Catalog npm
Back to packageRELEASE DETAILS

0.4.0

npm

98k

lightweight wrapper based on react, redux, redux-saga and react-router-dom

frameworkfrontendreactredux
Published2 Apr 2018
Direct dependencies11
Transitive dependenciesNot calculated

README

Current package documentation

98k

a lightweight wrapper based on react, redux, redux-saga and react-router-dom, that aims to free you from tedious steps of creating action creators, reducers, sagas etc(inspired by dva).

Install

$ npm install --save 98k

Quick start

index.js

import Kar98k from '98k';
import counter from './counter';

const app = Kar98k();
//app.middleware(middlewares); //apply redux middlewares here

app.module(counter);

app.start('#app');

counter.js

import React from 'react';
import { connect } from '98k';

const Counter = connect(state => state.counter)(({ dispatch, count }) => (
  <div>
    <div>count: {count}</div>
    <button onClick={() => dispatch({
      type    : 'counter/add',
      payload : 1,
    })}>add</button>
  </div>
));

export default {
  namespace : 'counter',
  state     : {
    count: 0,
  },
  reducers: {
    add(state, { payload }) {
      return { ...state, count: state.count + payload };
    },
  },
  routes: {
    '/': { component: Counter },
  },
};

actionType is the key properties of reducers prefixed by namespace.

Options

const app = Kar98k({
  router: 'hash', // 'hash','browser'
  basename: '/',  // the baseUrl used in react-router
});

Asynchronous action

const Counter = connect(state => state.counter)(({ dispatch, count }) => (
  <div>
    <div>count: {count}</div>
    <button onClick={() => dispatch({
      type    : 'counter/asyncAdd',
      payload : 2,
    })}>asyncAdd</button>
  </div>
));

export default {
  namespace : 'counter',
  state     : {
    count: 0,
  },
  effects: {
    *asyncAdd({ payload }, { put, call }, { delay }) {
      yield call(delay, 1000);
      yield put({ type: 'counter/add', payload });
    },
  },
  reducers: {
    add(state, { payload }) {
      return { ...state, count: state.count + payload };
    },
  },
  routes: {
    '/': { component: Counter },
  },
};

Routing

const App = connect(state => state.example)(({ match: { params: { id } } }) => (
  <div>routing example: {id}</div>
));

export default {
  namespace : 'example',
  routes    : {
    '/example/:id': { component: App },
  },
};

Navigate routes programmatically

export default {
  namespace: 'example',
  effects: {
    *redirectToRoutes({ payload }, { call }, { history }) {
      const { data } = call(services.someApi, payload);
      if(data) {
        history.push('/some/routes');
      } else {
        history.push('/other/routes');
      }
    },
  },
};

Error handling

export default {
  namespace : 'counter',
  state     : {
    count: 0,
  },
  effects: {
    *asyncAdd({ payload }, { put, call }, { delay }) {
      yield call(delay, 1000);
      throw 'some error';
      yield put({ type: 'counter/add', payload });
    },
  },
  catch: function*(err, action, { put }) {
    console.log(err);
    console.log(action);
    yield put({ type: 'counter/add', payload });
  },
  reducers: {
    add(state, { payload }) {
      return { ...state, count: state.count + payload };
    },
  },
  routes: {
    '/': { component: Counter },
  },
};

Plugin

you can add plugins via app.use.

index.js

import Kar98k from '98k';
import loading from './loading';
import counter from './counter';

const app = Kar98k();

app.use(loading())
  .module(counter)
  .start('#app');

A plugin is just a function that gets two parameters: injectReducer and injectEffect.

injectReducer is used to add extra reducers.

injectEffect is basically used to add a higher-order function that wraps saga function.

loading.js

export default (injectReducer, injectEffect) => {
  const initialState = {};

  injectReducer({
    loading(state = initialState, { type, payload }) {
      const { namespace } = payload || {};
      switch(type) {
        case '@@98k/show':
          return { 
            ...state, 
            [namespace]: true,
          };
        case '@@98k/hide':
          return { 
            ...state, 
            [namespace]: false,
          };
        default:
          return state;
      }
    },
  });

  injectEffect((saga, module, type, { put, call }, { delay }) => {
    const { namespace } = module;
    return function*(action) {
      yield put({ type: '@@98k/show', payload: { namespace, type } });
      yield saga(action);
      yield call(delay, 1000);
      yield put({ type: '@@98k/hide', payload: { namespace, type } });
    };
  });
}

parameters of injectEffect are:

saga - the current saga function that is being triggered

module - the module object that this saga belongs to

type - type of the current action

and saga helpers.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Declared dependencies 11

Native requirements
11 direct targetsNot calculated transitive count
Package / targetRequirementRelationship
react
Environment
{
  "local_name": "react",
  "alias": false,
  "peer_metadata": null
}
^16.3.0runtime
react-dom
Environment
{
  "local_name": "react-dom",
  "alias": false,
  "peer_metadata": null
}
^16.3.0runtime
react-redux
Environment
{
  "local_name": "react-redux",
  "alias": false,
  "peer_metadata": null
}
^5.0.7runtime
react-router-dom
Environment
{
  "local_name": "react-router-dom",
  "alias": false,
  "peer_metadata": null
}
^4.2.2runtime
redux
Environment
{
  "local_name": "redux",
  "alias": false,
  "peer_metadata": null
}
^3.7.2runtime
redux-saga
Environment
{
  "local_name": "redux-saga",
  "alias": false,
  "peer_metadata": null
}
^0.16.0runtime
babel-cli
Environment
{
  "local_name": "babel-cli",
  "alias": false,
  "peer_metadata": null
}
^6.26.0development
babel-core
Environment
{
  "local_name": "babel-core",
  "alias": false,
  "peer_metadata": null
}
^6.26.0development
babel-preset-es2015
Environment
{
  "local_name": "babel-preset-es2015",
  "alias": false,
  "peer_metadata": null
}
^6.24.1development
babel-preset-react
Environment
{
  "local_name": "babel-preset-react",
  "alias": false,
  "peer_metadata": null
}
^6.24.1development
babel-preset-stage-0
Environment
{
  "local_name": "babel-preset-stage-0",
  "alias": false,
  "peer_metadata": null
}
^6.24.1development

Distribution files

1 collected
Distribution 1

Source distribution

Source file
Checksums from source
{
  "integrity": "sha512-LMycR3ukwbGePPBDS7aqP1S7R0ouNPTFJanJJRH50hFygkXMgFTccbt09wSkiUeEKuFNTVPWJlfRt0UY6XbXrA==",
  "shasum": "ab6533852cdbda2be93287c51d1bcc522db4c99d",
  "tarball": "https://registry.npmjs.org/98k/-/98k-0.4.0.tgz",
  "fileCount": 8,
  "unpackedSize": 15648,
  "signatures": [
    {
      "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA",
      "sig": "MEUCIQDX87ceoIu39ACH6L0CWiA2b3t4PAxh/ueH8HHwEc6UuAIgSG2Wft+Fbbh7NffoM2SNe9VarpGr+f97MPGglBtK9MY="
    }
  ]
}

Repository

ACCESSIBLE
coiorz/98k

Shared repository data · GitHub

License detected in repository
Not collected
Last push
18 Apr 2018
Archived
No
Contributor identities
— · partial collection

Public sponsor counts have not been collected. These signals belong to the repository owner.

Downloads & popularity

0count
Gauge · observed snapshots22 Oct 2026
10.50
2026-10-22: 0 · observed 2026-10-22T16:06:30.8753448Z
22 Oct22 Oct

github · 1 observations shown. Missing days are unknown.

View observed values
Date / source periodValueObserved at
2026-10-2202026-10-22T16:06:30.8753448Z

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 21:33 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package_version:1e37b68ade4441e88c3f8a8c8b90ac0b970f4dcf069eb93d4efe4f4a4ddaebbe

Other collected versions

0.5.118 Apr0.5.017 Apr0.4.35 Apr0.4.22 Apr0.4.12 Apr0.3.12 AprView all collected versions →