微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

reudx-action构建工具redux-act

github路径:https://github.com/pauldijou/...

这是一个自用的工具用于创建actionsreducers用于redux。主要的目标是使用action本身作为reducer的引用而不是变量。

安装

npm install redux-act --save

用法

这里有一个名叫createAction函数,它用于创建一个action,和名叫createActionCreator方法有点接近。如果你不能确定是否是actionaction创造者,那么记住当action创造者是方法时,action是对象。

// Import functions
import { createStore } from 'redux';
import { createAction,createReducer } from 'redux-act';

// Create an action creator (description is optional)
const add = createAction('add some stuff');
const increment = createAction('increment the state');
const decrement = createAction('decrement the state');

// Create a reducer
// (ES6 Syntax,see Advanced usage below for an alternative for ES5)
const counterReducer = createReducer({
  [increment]: (state) => state + 1,[decrement]: (state) => state - 1,[add]: (state,payload) => state + payload,},0); // <-- This is the default state

// Create the store
const counterStore = createStore(counterReducer);

// dispatch actions
counterStore.dispatch(increment()); // counterStore.getState() === 1
counterStore.dispatch(increment()); // counterStore.getState() === 2
counterStore.dispatch(decrement()); // counterStore.getState() === 1
counterStore.dispatch(add(5)); // counterStore.getState() === 6

高级用法

import { createStore } from 'redux';
import { createAction,createReducer } from 'redux-act';

// You can create several action creators at once
// (but that's probably not the best way to do it)
const [increment,decrement] = ['inc','dec'].map(createAction);

// When creating action creators,the description is optional
// it will only be used for devtools and logging stuff.
// It's better to put something but feel free to leave it empty if you want to.
const replace = createAction();

// By default,the payload of the action is the first argument
// when you call the action. If you need to support several arguments,// you can specify a function on how to merge all arguments into
// an unique payload.
let append = createAction('optional description',(...args) => args.join(''));

// There is another pattern to create reducers
// and it works fine with ES5! (maybe even ES3 \o/)
const stringReducer = createReducer(function (on) {
  on(replace,(state,payload) => payload);
  on(append,payload) => state += payload);
  // Warning! If you use the same action twice,// the second one will override the prevIoUs one.
},'missing a lette'); // <-- Default state

// Rather than binding the action creators each time you want to use them,// you can do it once and for all as soon as you have the targeted store
// assignTo: mutates the action creator itself
// bindTo: returns a new action creator assigned to the store
const stringStore = createStore(stringReducer);
replace.assignTo(stringStore);
append = append.bindTo(stringStore);

// Now,when calling actions,they will be automatically dispatched
append('r'); // stringStore.getState() === 'missing a letter'
replace('a'); // stringStore.getState() === 'a'
append('b','c','d'); // stringStore.getState() === 'abcd'

// If you really need serializable actions,using string constant rather
// than runtime generated id,just use a uppercase description (with eventually some underscores)
// and it will be use as the id of the action
const doSomething = createAction('STRING_CONSTANT');
doSomething(1); // { type: 'STRING_CONSTANT',payload: 1}

// Little bonus,if you need to support Metadata around your action,// like needed data but not really part of the payload,you add a second function
const MetaAction = createAction('desc',arg => arg,arg => ({Meta: 'so Meta!'}));

// Metadata will be the third argument of the reduce function
createReducer({
  [MetaAction]: (state,payload,Meta) => payload
});

API说明

createAction([description],[payloadReducer],[MetaReducer])

参数

  • description(字符串,可选) 当显示的时候用于注册action名称和在开发者工具中使用。如果这个参数只是大写,它可以在不用生成任何id的情况下被用作action类型。你可以使用这个特性在服务端和客户端中有序整理action

  • payloadReducer(方法,可选) 转变多个参数作为唯一的payload

  • MetaReducer(方法,可选) 转变多个参数作为唯一的元数据对象。

用法

返回一个新的action构造器。如果你指定了description,它将被开发者工具使用。认情况下,createAction返回一个方法,并且触发它的时候第一个参数被作为payload。如果你想支持多个参数,你需要指定一个payloadReducer来把所有的参数合并到payload中。

// Super simple action
const simpleAction = createAction();
// Better to add a description
const betteraction = createAction('This is better!');
// Support multiple arguments by merging them
const multipleAction = createAction((text,checked) => ({text,checked}))
// Again,better to add a description
const bestAction = createAction('Best. Action. Ever.',(text,checked}))
// Serializable action (the description will be used as the unique identifier)
const serializableAction = createAction('SERIALIZABLE_ACTION');

action creator

action创造器基本上是一个携带参数并且返回action方法,它具有以下格式:

  • type:通过参数description生成id

  • payload:当调用action creator时进行数据传递,传递的是第一个参数除非在创建action时指定了payloadReducer.

  • Meta:如果你提供了MetaReducer,它将创建一个Metadata对象分配给这个key,否则它是undefined

const addTodo = createAction('Add todo');
addTodo('content');
// return { type: '[1] Add todo',payload: 'content' }

const editTodo = createAction('Edit todo',(id,content) => ({id,content}));
editTodo(42,'the answer');
// return { type: '[2] Edit todo',payload: {id: 42,content: 'the answer'} }

const serializetodo = createAction('SERIALIZE_Todo');
serializetodo(1);
// return { type: 'SERIALIZE_Todo',payload: 1 }

action creator有以下方法

getType()

返回生成的类型并被用于这个action creator的所有action

assignTo(store | dispatch)

记住你要触发这些actions,如果你有一个或多个stores,可以通过assignTo分配这些action。这会改变action creator本身,你可以传递一个store或者dispatch方法或者数组。

let action = createAction();
let action2 = createAction();
const reducer = createReducer({
  [action]: (state) => state * 2,[action2]: (state) => state / 2,});
const store = createStore(reducer,1);
const store2 = createStore(reducer,-1);

// Automatically dispatch the action to the store when called
action.assignTo(store);
action(); // store.getState() === 2
action(); // store.getState() === 4
action(); // store.getState() === 8

// You can assign the action to several stores using an array
action.assignTo([store,store2]);
action();
// store.getState() === 16
// store2.getState() === -2
bindTo(store | dispatch)

如果你需要不可变,你可以使用该方法。它将生成一个新的action creator并且能够自动触发action

// If you need more immutability,you can bind them,creating a new action creator
const boundAction = action2.bindTo(store);
action2(); // Not doing anything since not assigned nor bound
// store.getState() === 16
// store2.getState() === -2
boundAction(); // store.getState() === 8
assigned() / bound() / dispatched()

测试action creator的当前状态。

const action = createAction();
action.assigned(); // false,not assigned
action.bound(); // false,not bound
action.dispatched(); // false,test if either assigned or bound

const boundAction = action.bindTo(store);
boundAction.assigned(); // false
boundAction.bound(); // true
boundAction.dispatched(); // true

action.assignTo(store);
action.assigned(); // true
action.bound(); // false
action.dispatched(); // true
raw(...args)

action creator无论是分配还是绑定,将不再返回action对象而是触发它。有些情况下,你需要没有触发的action。为了达到这个目的,你可以使用raw方法返回纯粹的action

const action = createAction().bindTo(store);
action(1); // store has been updated
action.raw(1); // return the action,store hasn't been updated

createReducer(handlers,[defaultState])

参数

  • handlers(对象或方法):如果是方法则携带两个属性,一是注册action,二是取消注册,如下。

  • defaultState(任意,可选):reducer的初始状态,如果要在combineReducers使用千万不能为空。

用法

返回一个新的reducer。和Array.prototype.reduce的语法类似,你可以指定如何累加,比如第一个参数并累加,或者认的状态。认的状态是可选的,因为创建时可以在store获取,但你需要注意reducer中始终存在认状态,尤其是你要结合combineReducers使用时。
有两种创建reducer的方式,一种是通过对象集合,所有方法必须遵循prevIoUsstate,payload) => newState。另一种是使用工厂模式,话不多说,看下面的例子。

const increment = createAction();
const add = createAction();

// First pattern
const reducerMap = createReducer({
  [increment]: (state) => state + 1,payload) => state + payload
},0);

// Second pattern
const reducerFactory = createReducer(function (on,off) {
  on(increment,(state) => state + 1);
  on(add,payload) => state + payload);
  // 'off' remove support for a specific action
  // See 'Adding and removing actions' section
},0);

reducer

reducer就是一个方法。它当前的状态和行为并返回新的状态,有以下方法

options(object)

因为action是带有typepayload甚至还有Metadata的对象。所有的reduce方法认将payload作为它们的第二个参数,Metadata作为第三个参数,而不是所有的action。因为所有其他属性由lib处理不用关心。如果你要使用全部的action,你可以改变reducer的行为。

const add = createAction();
const sub = createAction();
const reducer = createReducer({
  [add]: (state,action) => state + action.payload,[sub]: (state,action) => state - action.payload
},0);

reducer.options({
  payload: false
});

has(action creator)

检测reducer是否含有reduce方法对于特定的action或者字符串类型。

const add = createAction();
const sub = createAction();
const reducer = createReducer({
  [add]: (state,action) => state + action.payload
},0);

reducer.has(add); // true
reducer.has(sub); // false
reducer.has(add.getType()); // true

on(action creator,reduce function) / off(action creator)

可以动态添加删除action。

assignAll(actionCreators,stores)

参数

  • actionCreators(对象或数组)

  • stores(对象或数组)

用法

普遍的方式是导出一系列的action作为对象,如果你需要将所有绑定到store,这里有一个超级小帮手。也可以使用action数组。

// actions.js
export const add = createAction('Add');
export const sub = createAction('Sub');

// reducer.js
import * as actions from './actions';
export default createReducer({
  [actions.add]: (state,[actions.sub]: (state,payload) => state - payload
},0);

// store.js
import * as actions from './actions';
import reducer from './reducer';

const store = createStore(reducer);
assignAll(actions,store);

export default store;

bindAll(actionCreators,stores)

参数

  • actionCreators(对象或数组)

  • stores(对象或数组)

用法

类似于assignAll,可以立刻绑定action

import { bindAll } from 'redux-act';
import store from './store';
import * as actions from './actions';

export bindAll(actions,store);

disbatch(store | dispatch,[actions])

参数

  • store | dispatch (对象,store或diaptch方法),在store添加disbatch方法,类似于diaptch,但这个是触发多个action

  • actions(数组,可选) 需要触发的一些action

用法

// All samples will display both Syntax with and without an array
// They are exactly the same
import { disbatch } from 'redux-act';
import { inc,dec } from './actions';

// Add 'disbatch' directly to the store
disbatch(store);
store.disbatch(inc(),dec(),inc());
store.disbatch([inc(),inc()]);

// disbatch immediately from store
disbatch(store,inc(),inc());
disbatch(store,[inc(),inc()]);

// disbatch immediately from dispatch
disbatch(store.dispatch,inc());
disbatch(store.dispatch,inc()]);

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐