redux 实现
- 安装额外插件
以 redux-xxx 命名的都是 redux 中间件,用于实现特定功能的一个函数
| 12
 3
 4
 
 | $ yarn add redux react-redux redux-thunk
 
 
 
 | 
打造 reducer
- src 下创建 reducers/index.ts
- 从 redux 引入 combineReducers
- 导出 rootReducer
| 12
 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
- 导出
| 12
 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
| 12
 
 | createStore(rootReducer, applyMiddleware(thunk));
 
 | 
Provider 跨组件通信
使用跨组件通信的方法将 store 的数据给所有的组件
- 进入 src 目录的 index.tsx 文件从 react-redux 中引入 Provider
- Provider 有个 store 属性 所以需要引入 store 文件
| 12
 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 中引入
| 12
 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 得到数据
| 12
 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
| 12
 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
 
- 导出
| 12
 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 中调用在这个组件上的方法
| 12
 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 分支判断调用的是哪个方法
| 12
 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;
 
 | 
拿到数据后就可以渲染了