Redux原始碼解讀 [03] 之 bindActionCreators
回顧 actionCreator
接下來說說 bindActionCreators 這個方法,bindActionCreators 不難理解,但在此之前需要回顧一下我們之前講到的 actionCreator 的概念,我們知道,要更新state樹的唯一途徑是發起一個action,如:
dispatch({
type: 'ADD_TODO',
text: 'ADD TODO AGAIN.'
})
每個action都需要寫type,這樣每次寫起來就會覺得冗餘,於是產生了 actionCreator 的概念,我們寫一個函式,幫我們寫好指定的type,傳入不同的資訊載荷就可以了,如:
function addTodo(text){
return{
type: 'ADD_TODO',
text
}
}
上面就是一個actionCreator 的例子,注意actionCreator 和action是兩個不同的概念,action是物件,用來描述state發生了什麼變化,而actionCreator 是函式,是用來生成action的工廠。
bindActionCreator 函式
再然後來看看bindActionCreators 方法用到的一個函式:
function bindActionCreator(actionCreator, dispatch) {
return function() {
return dispatch(actionCreator.apply(this, arguments))
}
}
函式的兩個引數:
* actionCreator 函式,用於生產action的工廠
* dispatch 函式,也就是Store.dispatch ()
函式非常簡單,也就是將 dispatch 和 actionCreator 繫結返回一個新的函式,使用這個函式時會直接 dispatch 一個 action,變得更加簡便,如:
let actionCreator = (text)=>({
type: 'ADD_TODO,
text
})
let addTodo = bindActionCreator(actionCreator , Store.dispatch)
// 呼叫
addTodo(' ADD SOMETHING’)
// 等價於:
dispatch({
type: 'ADD_TODO',
text: 'ADD SOMETHING'
})
也就是說 actionCreator 幫我們省略了重複書寫action.type , bindActionCreator 幫我們省略了重複書寫 dispatch,而且還可以隱藏 dispatch 引數。再來看看bindActionCreators方法就不難理解了:
bindActionCreators 方法
export default function bindActionCreators(actionCreators, dispatch) {
// 如果傳入的actionCreators是一個函式,則直接繫結返回一個新的函式
if (typeof actionCreators === 'function') {
return bindActionCreator(actionCreators, dispatch)
}
// 如果傳入的actionCreators是Object型別
// Object的欄位都是一個個 actionCreator
if (typeof actionCreators !== 'object' || actionCreators === null) {
throw new Error(
`xxxx`
)
}
const keys = Object.keys(actionCreators) // 所有的key
const boundActionCreators = {} // 最終返回的物件
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
const actionCreator = actionCreators[key]
// 過濾不合法的值 逐一進行繫結
if (typeof actionCreator === 'function') {
boundActionCreators[key] = bindActionCreator(actionCreator, dispatch)
}
}
//返回最終繫結好 actionCreator 物件
return boundActionCreators
}
最後
總結一下 bindActionCreators 方法,首先引數dispatch是必須的,也就是Store.dispatch()。
* 如果你傳入的 actionCreators 引數僅僅是一個 actionCreator 函式,那麼直接繫結 actionCreator 和 dispatch,返回一個新函式,呼叫函式傳入action的載荷,就可以直接發起一個指定type的action。
* 如果你傳入的 actionCreators 引數是一個物件,那麼物件的欄位必須是一個個actionCreator函式,返回一個物件,物件逐一進行繫結,每個欄位都是繫結好的函式,呼叫它們傳入action的載荷,就會直接發起一個指定type的action。
使用場景
Redux文件上關於何時使用到此API是這樣說的:
惟一會使用到 bindActionCreator 的場景是當你需要把 action creator 往下傳到一個元件上,卻不想讓這個元件覺察到 Redux 的存在,而且不希望把 dispatch 或 Redux store 傳給它。