redux
及react-redux
都只能实现数据的同步修改更新,有点类似于vue
中的mutation
,只能做同步操作,异步的话不用actions
来实现。由于在项目始终不可避免要实现的异步数据的更新,这明显不够用了。是时候引入我们的异步中间件redux-thunk
了
实现效果
代码实现
- 安装
redux-thunk
bash
npm i redux-thunk
- store/index.js
js
import { createStore, applyMiddleware, compose } from "redux";
import { combineReducers } from "redux-immutable";
import { thunk } from "redux-thunk";
import { CounterReducer } from "./CounterReducer";
const reducers = combineReducers({
count: CounterReducer,
});
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
const store = createStore(reducers, composeEnhancers(applyMiddleware(thunk)));
export default store;
- CounterReducer.js
封装了两个异步方法,模拟数据的异步获取,然后导出供其他组件使用
js
import { fromJS } from "immutable";
const initialState = fromJS({
counter: 0,
userInfo: {
name: "John Doe",
age: 25,
},
});
function CounterReducer(state = initialState, action) {
console.log("🚀 ~ CounterReducer ~ action:", action);
switch (action.type) {
case "ADD":
return state.update("counter", (val) => {
return val + 1;
});
case "ADD_TWO":
return state.update("counter", (val) => {
return val + 2;
});
case "DEC":
return state.update("counter", (val) => val - 1);
case "DEC_TWO":
return state.update("counter", (val) => val - 2);
case "CHANGE_NAME":
return state.setIn(["userInfo", "name"], action.payload);
default:
return state;
}
}
// async action 2s later
function handleDelayAdd() {
return (dispatch) => {
// 模拟异步接口
setTimeout(() => dispatch({ type: "ADD_TWO" }), 2000);
};
}
// async action 2s later
function handleDelayReduce() {
return (dispatch) => {
// 模拟异步接口
setTimeout(() => dispatch({ type: "DEC_TWO" }), 2000);
};
}
export { CounterReducer, handleDelayAdd, handleDelayReduce };
- DemoB.js
引入两个异步的方法,注意跟同步的dispatch
使用方法有点区别,dispatch(handleDelayAdd())
在dispatch
直接调用了该方法
js
import { useSelector, useDispatch } from "react-redux";
import { Button, Space, Divider } from "antd";
import { handleDelayAdd, handleDelayReduce } from "../../store/CounterReducer";
function DemoB() {
const count = useSelector((state) => state.getIn(["count", "counter"]));
const userInfo = useSelector((state) => state.getIn(["count", "userInfo"]));
const dispatch = useDispatch();
return (
<div>
<p>Demo B</p>
<div>
<Space split={<Divider />}>
<span>name: {userInfo.get("name")}</span>
<span>age: {userInfo.get("age")}</span>
<span>count:{count}</span>
</Space>
</div>
<Space>
<Button type="primary" onClick={() => dispatch({ type: "ADD" })}>
add count
</Button>
<Button type="primary" danger onClick={() => dispatch({ type: "DEC" })}>
minus count
</Button>
<Button type="primary" onClick={() => dispatch(handleDelayAdd())}>
delay 2s add count
</Button>
<Button
type="primary"
danger
onClick={() => dispatch(handleDelayReduce())}
>
delay 2s minus count
</Button>
<Button
type="dashed"
danger
onClick={() => dispatch({ type: "CHANGE_NAME", payload: "张学友" })}
>
change name
</Button>
</Space>
</div>
);
}
export default DemoB;
这样我们就实现了在react项目中数据的异步更新。整体还是比较简单的。
总结
在这个具有副作用的action中,我们可以看出,函数内部可能极为复杂。如果需要为每一个异步操作都如此定义一个action,显然action不易维护。
action不易维护的原因:
- action的形式不统一
- 就是异步操作太为分散,分散在了各个action中