98k 中文文档教程

发布于 7年前 浏览 38 项目主页 更新于 3年前

98k

一个基于 react、redux、redux-saga 和 react-router-dom 的轻量级包装器,旨在将您从创建 action creator、reducer、sagas 等(受 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 是 reducers 的关键属性,前缀为 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 },
  },
};
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

您可以通过 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');

插件只是一个获取两个参数的函数:injectReducerinjectEffect

injectReducer 用于添加额外的 reducer。

injectEffect 基本上用于添加包装 saga 函数的高阶函数。

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 } });
    };
  });
}

>loading.js injectEffect 的参数是:

saga - 当前被触发的 saga 函数

module - 模块此 saga 属于

type 的对象 - 当前操作

和 saga 助手的类型。

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 },
  },
};
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.

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文