github路徑:https://github.com/pauldijou/...javascript
這是一個自用的工具用於建立actions
和reducers
用於redux
。主要的目標是使用action
自己做爲reducer
的引用而不是變量。java
npm install redux-act --save
這裏有一個名叫createAction
的函數,它用於建立一個action
,和名叫createActionCreator
的方法有點接近。若是你不能肯定是不是action
或action
創造者,那麼記住當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 });
description(字符串,可選) 當顯示的時候用於註冊action名稱和在開發者工具中使用。若是這個參數只是大寫,它能夠在不用生成任何id的狀況下被用做action
類型。你可使用這個特性在服務端和客戶端中有序整理action
。github
payloadReducer(方法,可選) 轉變多個參數做爲惟一的payload
。npm
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
創造器基本上是一個攜帶參數而且返回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
有如下方法:
返回生成的類型並被用於這個action creator
的全部action
。
記住你要觸發這些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
若是你須要不可變,你可使用該方法。它將生成一個新的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
測試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
當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
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
就是一個方法。它當前的狀態和行爲並返回新的狀態,有如下方法:
由於action
是帶有type
、payload
甚至還有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 });
檢測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
能夠動態添加或刪除action。
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;
actionCreators(對象或數組)
stores(對象或數組)
相似於assignAll
,能夠馬上綁定action
。
import { bindAll } from 'redux-act'; import store from './store'; import * as actions from './actions'; export bindAll(actions, store);
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()]);