ReduxのMiddlewareの原理
2883 ワード
ReduxのMiddlewareの原理
次に、redux-trunkを例に、applyMiddlewareが何に使用されるかを説明します.
redux-thunk/src/index.js
まず上のコードからtrunkは({dispatch,getState})=>{}という矢印関数であることがわかる.applyMiddleware(trunk)が実行されると、redux/src/applyMiddleware.js
applyMiddleware関数から,戻りも関数であり,trunkは前のパラメータmiddlewaresという閉パケット配列の1つとして機能することが分かった.次にcreateStore関数に入ります
転送パラメータはconst store=createStore(...args)転送reducerが新しいstoreを作成し、middlewareAPIの2つのプロパティを作成し、dispatch関数のargsが外部のargsではないことを覚えておいて、混同しないでください.trunkにこのオブジェクトが入力されてnext=>{}という関数が返されると、chainはこの関数になります.compose関数演算に入るとnext=>{}関数自体が返され、再び計算するとaction=>{}という関数が返されます.つまりdispatch関数はaction=>{}という関数です.まとめ:(1)action=>{}関数のnextはstore.dispatchを指す.(2)createStore()ミドルウェアがあって戻ってくるdispatchはミドルウェアが入ってこないdispatchではなく、action=>{}関数であり、storeのdispatchはnext閉パケット変数として入ってくる.(3)createThunkMiddleware関数から分かるように、actionが関数である場合にaction(dispatch,getState,extraArgument)を実行する.なお、ここでのdispatchはstoreのdispatchではなく、applyMiddlewareで宣言されているdispatchである.dispatch=compose(...chain)(store.dispatch)はdispatch(参照データ型、メモリ指向が同じ)を再定義しているため、actionに入力されたdispatchは実行時にmiddlewareAPIのdispatchを実行し、実行時にnextを呼び出す(createStoreにおけるdispatchメソッド);(4)非同期処理の場合、actionはimportでstoreのdispatchメソッドを取得できず(actionではこの場合storeは確立されていない)、storeにおけるdispatchメソッドをミドルウェアで閉パケットに渡して保存し、非同期トリガを実現する.
次に、redux-trunkを例に、applyMiddlewareが何に使用されるかを説明します.
redux-thunk/src/index.js
function createThunkMiddleware(extraArgument) {
return ({ dispatch, getState }) => next => action => {
if (typeof action === 'function') {
return action(dispatch, getState, extraArgument);
}
return next(action);
};
}
const thunk = createThunkMiddleware();
thunk.withExtraArgument = createThunkMiddleware;
export default thunk;
まず上のコードからtrunkは({dispatch,getState})=>{}という矢印関数であることがわかる.applyMiddleware(trunk)が実行されると、redux/src/applyMiddleware.js
export default function applyMiddleware(...middlewares) {
return createStore => (...args) => {
const store = createStore(...args)
let dispatch = () => {
throw new Error(
`Dispatching while constructing your middleware is not allowed. ` +
`Other middleware would not be applied to this dispatch.`
)
}
const middlewareAPI = {
getState: store.getState,
dispatch: (...args) => dispatch(...args)// args args
}
const chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
applyMiddleware関数から,戻りも関数であり,trunkは前のパラメータmiddlewaresという閉パケット配列の1つとして機能することが分かった.次にcreateStore関数に入ります
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
enhancer = preloadedState
preloadedState = undefined
}
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
throw new Error('Expected the enhancer to be a function.')
}
// enhancer applyMiddleware
//reducer ,preloadedState undefined
return enhancer(createStore)(reducer, preloadedState)
}
転送パラメータはconst store=createStore(...args)転送reducerが新しいstoreを作成し、middlewareAPIの2つのプロパティを作成し、dispatch関数のargsが外部のargsではないことを覚えておいて、混同しないでください.trunkにこのオブジェクトが入力されてnext=>{}という関数が返されると、chainはこの関数になります.compose関数演算に入るとnext=>{}関数自体が返され、再び計算するとaction=>{}という関数が返されます.つまりdispatch関数はaction=>{}という関数です.まとめ:(1)action=>{}関数のnextはstore.dispatchを指す.(2)createStore()ミドルウェアがあって戻ってくるdispatchはミドルウェアが入ってこないdispatchではなく、action=>{}関数であり、storeのdispatchはnext閉パケット変数として入ってくる.(3)createThunkMiddleware関数から分かるように、actionが関数である場合にaction(dispatch,getState,extraArgument)を実行する.なお、ここでのdispatchはstoreのdispatchではなく、applyMiddlewareで宣言されているdispatchである.dispatch=compose(...chain)(store.dispatch)はdispatch(参照データ型、メモリ指向が同じ)を再定義しているため、actionに入力されたdispatchは実行時にmiddlewareAPIのdispatchを実行し、実行時にnextを呼び出す(createStoreにおけるdispatchメソッド);(4)非同期処理の場合、actionはimportでstoreのdispatchメソッドを取得できず(actionではこの場合storeは確立されていない)、storeにおけるdispatchメソッドをミドルウェアで閉パケットに渡して保存し、非同期トリガを実現する.