dispatch是派发action的入口,所有的action都是从dispatch这里派发的。
所以dispatch这里是一个重要的结点,
dispatch是脱离里业务的,所以如果能对dispatch进行二次封装,就可以达到修改整个redux的dispatch功能,从而
加强整个dispatch功能.
例如:我们如何改造dispatch方法,使得每次派发action时,都可以通过console.log打印出相关信息,方便我们更加清晰地了解store当中的state的每一步变更?
dispatch实质上是一个函数,它负责调用reducer方法,依靠reducer的执行进行状态变更,接着依次执行各监听函数,目的是实现视图的更新。
这样,我们的入手点就应该在dispatch函数调用的前后,插入console.log状态的输出。Redux的数据更新是同步进行的,最容易想到的办法是在业务代码中每一次store.dispatch(action)执行前后都手动进行记录。
如下:
console.log(action + 'will dispatch'); console.log(store.getState) store.dispatch(action) console.log(action + 'already dispatched') console.log(store.getState())
//这里的问题是我们不能在代码中粗暴地加入零散的 console.log,应该统一通过扩展dispatch方法来实现
//为了改造dispatch函数,我们按照如下步骤进行操作:
1、创建一个名为addLoggingToDispatch的函数,用来生成取代 "原始经典的dispatch"的全新dispatch方法。
这个函数需要对store中的dispatch进行拦截,并记录原始的dispatch为rawDispatch方法。同时,addLoggingToDispatch
函数应该在行为上同原始的dispatch保持一致,为此该函数返回一个新的函数,这个新的函数就是添加更新日志之后的全新dispatch。
所以这个返回函数自然要模仿rawDispatch的行为,将action作为参数
const addLoggingToDispatch = (store) => { const rawDispatch = store.dispatch; //返回的函数就是添加更新日志之后的全新的dispatch return action => { //... } }
2、在返回的函数中,我们需要调用真实的rawDispatch方法,还原原始的dispatch的行为,同时在调用rawDispatch前后
进行日志记录。需要注意的是,为了最大限度地还原原始的dispatch的行为,需要记录dispatch的返回值,并最终进行返回。
const addLoggingToDispatch = (store) => { const rawDispatch = store.dispatch; return (action) => { console.log(action.type); console.log('previous state', store.getState()); console.log('action', action); const retureValue = rawDispatch(action); console.log('next state', store.getState()); console.group(action.type); return retureValue; } }
3、最后加入对开发环境和生产环境的判断,我们只希望这些日志输出在开发阶段,方便调式,不适合在生产环境输出。
因此在重写store.dispatch之前,先进行环境判断。
if(process.env.NODE_ENV !== 'production') { store.dispatch = addLoggingToDispatch(store); }