redux 实现
- 安装额外插件
以 redux-xxx 命名的都是 redux 中间件,用于实现特定功能的一个函数
1 2 3 4
| $ yarn add redux react-redux redux-thunk
|
打造 reducer
- src 下创建 reducers/index.ts
- 从 redux 引入 combineReducers
- 导出 rootReducer
1 2 3 4 5 6 7 8 9
| import { combineReducers } from "redux";
const rootReducer = combineReducers({ });
export default rootReducer;
|
combineReducers
用于合并 reducer
打造 store
- src 下创建 models/index.ts
- 从 redux 中引入 createStore, applyMiddleware
- 从 redux-thunk 引入 thunk
- 引入刚才打造的 rootReducer
- 导出
1 2 3 4 5 6 7 8 9
| import { createStore, applyMiddleware } from "redux"; import thunk from "redux-thunk"; import rootReducer from "../reducers";
const store = createStore(rootReducer, applyMiddleware(thunk));
export default store;
|
createStore + applyMiddleware + thunk
1 2
| createStore(rootReducer, applyMiddleware(thunk));
|
Provider 跨组件通信
使用跨组件通信的方法将 store 的数据给所有的组件
- 进入 src 目录的 index.tsx 文件从 react-redux 中引入 Provider
- Provider 有个 store 属性 所以需要引入 store 文件
1 2 3 4 5 6 7 8
| import { Provider } from "react-redux"; import store from "./models";
<Provider store={store}> <App /> </Provider>;
|
创建 子 reducer
- 初始化数据 initState
- 定义一个 Reducer 函数
- 参数 state 就是数据
- action 就是一个对象,由 actionCreators 发过来的
- Reducer 一定有返回值,返回一个新的 state
- 导出
- 在 rootReducer 中引入
1 2 3 4 5 6 7 8 9
| const initState = { hotList: [], };
const hotReducer = (state = initState, action: any) => { return { ...state }; };
export default hotReducer;
|
在组件获取数据
- 组件需要通过一个叫做【connect 的返回值】的高阶组件来获取 store 中的数据
- 通过第一个回调函数的参数 state 获取数据,state 是全部数据,需要 return state.xxx, 并且需要给 state 赋予类型
- 组件就可以通过 props 得到数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| import React from "react"; import { connect } from "react-redux";
interface P { hotList: { [key: string]: any }; } function Hot(props: P) { return <div></div>; }
export default connect((state: { hot: {} }) => { return state.hot; })(Hot);
|
connect + bindActionCreators
- connect(callback1,callback2)(组件) 有两个回掉函数
- 第一个参数用于获取 store 的 state
- state 参数
- return state.xxx
- 第二个参数是用于获取 redux 的 actionCreators 中的创建动作的方法的
- dispatch 参数
- return bindActionCreators(动作,dispatch)
打造接口 service
创建 src/service/index.ts
1 2 3 4 5 6 7 8 9 10
| export const fetchHotListReq = (params: { cid: number }) => { return new Promise((resolve, reject) => { fetch(`http://59.110.226.77:3000/api/list/hot?cid=${params.cid}`) .then((data) => data.json()) .then((res) => { resolve(res); }) .catch((error) => reject(error)); }); };
|
打造 actions
- 创建 src/actions 文件夹
- 定义动作对象
- 对象里面写函数
- 参数 dispatch 类型 从 redux 引入 Dispatch
- 写逻辑
- 用 dispatch({type:常量,payload:结果}) 发送给 reducer
- 导出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| import { Dispatch } from "redux"; import * as service from "../service"; const hotActions = { getHotList(params: { cid: number }) { return async (dispatch: Dispatch) => { const result = service.fetchHotListReq(params); dispatch({ type: "GET_HOT_LIST", payload: result, }); }; }, };
export default hotActions;
|
激活 actions
- 回到组件引入 xxActions.ts
- 从 redux 引入 bindActionCreators
- 写 connect 的第二个回调函数
- 参数为 dispatch
- return bindActionCreators(xxActions, dispatch);
- 从 props 中调用在这个组件上的方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| import React, { useEffect } from "react"; import { connect } from "react-redux"; import hotActions from "../../actions/hotActions"; import { bindActionCreators } from "redux";
interface P { hotList: { [key: string]: any }; getHotList: (params: { cid: number }) => any; } function Hot(props: P) { const { hotList, getHotList } = props; useEffect(() => { getHotList({ cid: 17, }); }, []); return <div></div>; }
export default connect( (state: { hot: {} }) => { return state.hot; }, (dispatch) => { return bindActionCreators(hotActions, dispatch); } )(Hot);
|
调用方法后会 dispatch 到 reducer 身上
- console.log(action) 发现有 type 和 payload 属性
- 在 reducer 里写 switch 分支判断调用的是哪个方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const initState = { hotList: [], };
const hotReducer = (state = initState, action: any) => { switch (action.type) { case "GET_HOT_LIST": return { ...state, hotList: action.payload.data.content }; default: return { ...state }; } };
export default hotReducer;
|
拿到数据后就可以渲染了