reudx-action構建工具(redux-act)

github路徑:https://github.com/pauldijou/...javascript

這是一個自用的工具用於建立actionsreducers用於redux。主要的目標是使用action自己做爲reducer的引用而不是變量。java

安裝

npm install redux-act --save

用法

這裏有一個名叫createAction的函數,它用於建立一個action,和名叫createActionCreator的方法有點接近。若是你不能肯定是不是actionaction創造者,那麼記住當action創造者是方法時,action是對象。git

// 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, (state, 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類型。你可使用這個特性在服務端和客戶端中有序整理actiongithub

  • payloadReducer(方法,可選) 轉變多個參數做爲惟一的payloadnpm

  • metaReducer(方法,可選) 轉變多個參數做爲惟一的元數據對象。redux

用法

返回一個新的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) => ({text, checked}))
// Serializable action (the description will be used as the unique identifier)
const serializableAction = createAction('SERIALIZABLE_ACTION');

action creator

action創造器基本上是一個攜帶參數而且返回action的方法,它具備如下格式:app

  • type:經過參數description生成idide

  • 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,
  [add]: (state, payload) => state + payload
}, 0);

// Second pattern
const reducerFactory = createReducer(function (on, off) {
  on(increment, (state) => state + 1);
  on(add, (state, 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, payload) => state + payload,
  [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(), dec(), inc()]);

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

// Disbatch immediately from dispatch
disbatch(store.dispatch, inc(), dec(), inc());
disbatch(store.dispatch, [inc(), dec(), inc()]);
相關文章
相關標籤/搜索