redux中的reducer函数主要目的是制定更新规则,如果reduce中的action是一个异步的或者是一个函数的时候就会报错实例如下
调用方法
const delayed = ()=>{
store.dispatch(()=>{
setTimeout(() => {
store.dispath({type:"ADD"})
}, 1000);
})
}
执行结果
![](https://img.haomeiwen.com/i2355079/e523dae31c660409.png)
报错原因说action必须使用明确的action,你可以使用带中间件的异步action
- 使用中间件
需要安装3个中间件- 第一步
yarn add redux-logger redux-promise redux-thunk
- 第二步修改createStore方法
import {createStore, applyMiddleware, combineReducers} from "redux";
import thunk from "redux-thunk";
import logger from "redux-logger";
import promise from "redux-promise";
function countReducer(state=0,action) {
debugger
switch(action.type){
case "ADD":
return state+=1
case "MINUS":
return state -=1
default:
return state
}
}
const store = createStore(countReducer,applyMiddleware(promise,thunk,logger))
export default store
修改完成,在执行dispatch为函数或者为promise都可以
- 注意 logger最好写在最后,不然不能很好的捕捉日志
仿写中间件 logger thunk 和promise
- 代码思路:所谓的中间件其实就是对现有的createStore进行增强,返回的结果也应该和createStore保持一致。增强只是说对dispatch进行增强。同时也需要执行一遍中间件(函数)
- 修改createStore函数
export default function createStore(reducer,enhancer){
//enhancer 表示applyMiddleware 执行结果
if (enhancer){
//enhancer(createStore) 返回一个函数,相当于把createStore函数传递到函数中,在此执行这个函数,参数为reducer
return enhancer(createStore)(reducer)
}
// reducer 表示一个函数
let currentState;
let currentListeners =[]
function getState() {
return currentState
}
function dispatch(action) {
currentState = reducer(currentState,action)
currentListeners.forEach(listener =>listener())
}
function subscribe(listener) {
currentListeners.push(listener)
return () =>{
const index = currentListeners.indexOf(listener)
currentListeners.splice(index,1)
}
}
dispatch({type:"REDXXXXXXXX"})
return {
getState,
subscribe,
dispatch
}
}
- 创建 applyMiddleware文件并导出
export default function applyMiddleware(...middlewares) {
//这个地方可以改为 createStore =>reducer =>{} 函数样式
return createStore => {
return reducer => {
const store = createStore(reducer) //调用createStore函数,返回值为
// store = {getState, subscribe,dispatch}
let dispatch = store.dispatch //取出store中的dispath函数,主要目的是传递给中间件(函数使用)
const midApi = { //定义一个中间件使用的对象
getState: store.getState,
dispatch: action => dispatch(action)
}
// 把midApi 传递给中间件
const middlewareChain = middlewares.map(middleware => middleware(midApi)) //注意,这个地方需要结合中间件函数一起看, 返回next => action =>{}函数总数为2 一个为thunk的返回值一个为logger返回值
let res = compose(...middlewareChain) //返回一个函数,logger的
dispatch =res(store.dispatch)//执行compose函数 dispatch 返回的就是thunk中的 action =>{} 函数
// 返回增强的store,其实把dispatch增强就行了
return {
...store,
dispatch
};
}
}
}
function compose(...funs) {
// 这个空数组的兼容情况
if (funs.length === 0) {
return arg => arg;
}
if (funs.length === 1) {
return funs[0];
}
// 这个返回值是个函数
let r= funs.reduce((a, b) => (...args) => a(b(...args)));
return r
}
- 中间件(函数)的创建
import {createStore, applyMiddleware, combineReducers} from "redux";
// import thunk from "redux-thunk";
// import logger from "redux-logger";
// import promise from "redux-promise";
// import {createStore,applyMiddleware} from '../vRedux/index'
function countReducer(state=0,action) {
debugger
switch(action.type){
case "ADD":
return state+=1
case "MINUS":
return state -=1
default:
return state
}
}
// ,
const store = createStore(countReducer,applyMiddleware(thunk,logger))
// thunk处理异步
function thunk({dispatch, getState}) {
// next 通过comose函数,next其实就是logger函数,action函数就是dispatch中的函数dispatch(A) A =action,首先要判断action是对象还是函数,如果是函数的话,首先执行函数,因为在action(dispatch, getState);函数体重,仍然有dispatch函数的调用,它会再次进入这个函数,只不过这个参数为对象,因为next =logger函数返回的action=>{}函数,所以进入logger函数
return next => action => {
if (typeof action === "function") {
return action(dispatch, getState);
}
return next(action);
};
}
// ! 注意了: logger一定要放在applyMiddleware最后一个参数,因为放在前面的话,可能或没有type值,
// ! 比如说thunk处理的函数也是’action‘,但是就没有type值
function logger({dispatch, getState}) {
return next => action => {
//logger函数中 next为createStore 方法中dispatch函数,这是因为在compose函数调用的时候传递的为store.dispatch函数,action 表示操作类型action={type:XXX}
console.log("start *************************************");
console.log(action.type + "执行啦"); //sy-log
// dispatch执行前的state
const prevState = getState(); //这表示当前的state状态
console.log("prev state" + prevState, JSON.stringify(prevState)); //sy-log
// 相当于dispatch执行完了,数据已经发生变化
const returnValue = next(action); //正式执行了dispatch(action)函数,state发生了变化
const nextState = getState(); //最新的状态
console.log("next state" + nextState, JSON.stringify(nextState)); //sy-log
console.log("end *************************************");
return returnValue;
};
}
export default store
网友评论