redux 使用redux-thunk把switch从代码里踢出去
一些插件介绍
https://www.cnblogs.com/vvjiang/p/9505646.html
主要思想是将所有的有效修改进行合并
使用redux-thunk插件主要是为了能够支持异步, 以及可以传入函数
thunk的源码, 支持传入函数
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;
优点是不需要各种switch了, 使用起来会简单不少, 但是过于灵活也使得不小心就会出现一些bug… 比如一般而言可以在switch分action写log, 查错也简单, 但是这种方式就是直接合并对象, 增加了调试成本….
import React, { useState } from "react";
import { createStore, applyMiddleware } from "redux";
import { Provider, useSelector, useDispatch } from "react-redux";
import km from "keymirror";
import * as R from "ramda";
import thunk from "redux-thunk";
import { composeWithDevTools } from "redux-devtools-extension";
const ACTION_TYPES = km({
INC_A: null,
DEC_A: null,
INC_B: null,
DEC_B: null,
});
const initState = {
A: { count: 1 },
B: { count: 2 },
};
const reducerCreater = (actionTypes, initState) => (
state = initState,
{ type, pyload }
) => {
console.log("type", type, pyload, state);
if (pyload && type in actionTypes) {
return R.mergeRight(state, pyload);
}
return state;
};
const reducer = reducerCreater(ACTION_TYPES, initState);
const configStore = (preloadStore) => {
const middlewares = [thunk.withExtraArgument({})];
const middlewareEnhancers = applyMiddleware(...middlewares);
const enhancers = [middlewareEnhancers];
const composedEnhances = composeWithDevTools(...enhancers);
const store = createStore(reducer, preloadStore, composedEnhances);
return store;
};
const store = configStore();
const incA = (dx = 1) => (dispatch, getState) => {
const A = R.path(["A"], getState());
let aLens = R.lensPath(["count"]);
let newA = R.over(aLens, R.add(dx), A);
dispatch({
type: ACTION_TYPES.INC_A,
pyload: { A: newA },
});
};
const incB = (dx = 1) => (dispatch, getState) => {
const bLens = R.lensPath(["B", "count"]);
let newState = R.over(bLens, R.add(dx), getState());
dispatch({
type: ACTION_TYPES.INC_B,
pyload: newState,
});
};
const Counter = () => {
const dispatch = useDispatch();
const [dx, setDx] = useState(1);
const addA = () => {
dispatch(incA(dx));
};
const addB = () => {
dispatch(incB(dx));
};
const countA = useSelector(R.path(["A", "count"]));
const countB = useSelector(R.path(["B", "count"]));
return (
<div>
<input
value={dx}
type="number"
onChange={(el) => setDx(Number(el.target.value))}
/>
<div>
countA:{countA}, countB:{countB}
</div>
<button onClick={addA}>addA</button>
<button onClick={addB}>addB</button>
</div>
);
};
export default () => {
return (
<Provider store={store}>
<Counter></Counter>
</Provider>
);
};