redux-thunk
将 api 请求放在组件中并不合理:
- 如果用户不通过这个组件跳到其他组件,则会导致没有数据
 - 如果多个组件都请求相同的数据,则违反DRY原则,且项目难以维护
 
所以有必要将 api 请求转移到 redux store 中
Redux Thunk中间件允许action creator返回一个函数,用于推迟 action 的 dispatch 或者在特定条件下才dispatch,内部函数接受 store 的 dispatch 和 getState 作为参数
安装
安装redux-thunk
yarn add redux-thunk
初始化
在初始化store时允许使用thunk
import { createStore, applyMiddleware } from 'redux';import thunk from 'redux-thunk';import rootReducer from './reducers/index';// Note: this API requires redux@>=3.1.0const store = createStore(rootReducer, applyMiddleware(thunk));
初始化时可以使用withExtraArgument传入更多参数,如果有多个额外参数,可传入对象,如{api, Whatever}
const store = createStore(reducer,applyMiddleware(thunk.withExtraArgument(api)),);// laterfunction fetchUser(id) {return (dispatch, getState, api) => {// you can use api here};}
创建action creator
将 api 异步请求写到 action creator 里
- 注意 ThunkAction 里的泛型
 - 在thunk action中可以完成一系列 dispatch 操作
```tsx
export const getProductCollectionsActionCreator = ():ThunkAction<
void, 
RootState, 
unknown,
RecommendProductsAction
=> { return async (dispatch, getstate) => {
dispatch(fetchRecommendProductsStartActionCreator())try {const {data} = await axios.get('/api/productCollections')dispatch(fetchRecommendProductsSuccessActionCreator(data))}catch(error: any) {dispatch(fetchRecommendProductsFailActionCreator(error.message))}}
 
}
<a name="LXdx6"></a>#### 在组件中使用在类组件中使用```typescriptclass HomePageComponent extends React.Component<PropsType> {componentDidMount(){this.props.getProductsCollection()}// ...}const mapDispatchToProps = (dispatch) => {return {getProductsCollection: () => {dispatch(getProductCollectionsActionCreator())}}}
自定义中间件
redux中间件的机制是劫持action, 进行进一步的封装, next = store.dispatch
redux中间件的公式
const middleware = (store) => (next) => (action) => {}
自定义 actionlog 中间件
import { Middleware } from "redux";export const actionLog: Middleware = (store) => (next) => (action) => {console.log("state 更新前", store.getState())console.log("fire action", action)next(action) // dispatch actionconsole.log("state 更新后", store.getState())}
使用 actionLog 中间件
import thunk from 'redux-thunk'import { actionLog } from './middlewares/actionLog'const store = createStore(rootReducer, applyMiddleware(thunk, actionLog))
这样,在每次dispatch 中间件的时候,都会经过中间件, 执行中间件中的逻辑
