React reduex

React reduex

一月 24, 2021

redux 实现

  1. 安装额外插件

以 redux-xxx 命名的都是 redux 中间件,用于实现特定功能的一个函数

1
2
3
4
$ yarn add redux react-redux redux-thunk
# redux 构建redux架构
# react-redux 用户数据划分
# redux-thunk 异步数据交互[ 处理前后端交互 ]

打造 reducer

  1. src 下创建 reducers/index.ts
  2. 从 redux 引入 combineReducers
  3. 导出 rootReducer
1
2
3
4
5
6
7
8
9
// 打造reducers
import { combineReducers } from "redux";

// rootReducer 统一管理项目中的所有reducer
const rootReducer = combineReducers({
// 数据名: reducer
});

export default rootReducer;

combineReducers

用于合并 reducer

打造 store

  1. src 下创建 models/index.ts
  2. 从 redux 中引入 createStore, applyMiddleware
  3. 从 redux-thunk 引入 thunk
  4. 引入刚才打造的 rootReducer
  5. 导出
1
2
3
4
5
6
7
8
9
// 用于打造redux构成之一 store
import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import rootReducer from "../reducers";

// const store = createStore(rootReducer,中间件执行函数)
const store = createStore(rootReducer, applyMiddleware(thunk));

export default store;

createStore + applyMiddleware + thunk

1
2
// createStore(根Reducer,中间件执行函数)
createStore(rootReducer, applyMiddleware(thunk));

Provider 跨组件通信

使用跨组件通信的方法将 store 的数据给所有的组件

  1. 进入 src 目录的 index.tsx 文件从 react-redux 中引入 Provider
  2. Provider 有个 store 属性 所以需要引入 store 文件
1
2
3
4
5
6
7
8
// index.tsx
import { Provider } from "react-redux";
import store from "./models";
// ...
<Provider store={store}>
<App />
</Provider>;
// ...

创建 子 reducer

  1. 初始化数据 initState
  2. 定义一个 Reducer 函数
    • 参数 state 就是数据
    • action 就是一个对象,由 actionCreators 发过来的
    • Reducer 一定有返回值,返回一个新的 state
  3. 导出
  4. 在 rootReducer 中引入
1
2
3
4
5
6
7
8
9
const initState = {
hotList: [],
};

const hotReducer = (state = initState, action: any) => {
return { ...state };
};

export default hotReducer;

在组件获取数据

  1. 组件需要通过一个叫做【connect 的返回值】的高阶组件来获取 store 中的数据
  2. 通过第一个回调函数的参数 state 获取数据,state 是全部数据,需要 return state.xxx, 并且需要给 state 赋予类型
  3. 组件就可以通过 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: {} }) => {
// console.log(state); // state是全局的数据
return state.hot;
})(Hot);

connect + bindActionCreators

  1. 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

  1. 创建 src/actions 文件夹
  2. 定义动作对象
  3. 对象里面写函数
    • 参数 dispatch 类型 从 redux 引入 Dispatch
    • 写逻辑
    • 用 dispatch({type:常量,payload:结果}) 发送给 reducer
  4. 导出
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

  1. 回到组件引入 xxActions.ts
  2. 从 redux 引入 bindActionCreators
  3. 写 connect 的第二个回调函数
    • 参数为 dispatch
    • return bindActionCreators(xxActions, dispatch);
  4. 从 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: {} }) => {
// console.log(state); // state是全局的数据
return state.hot;
},
(dispatch) => {
return bindActionCreators(hotActions, dispatch);
}
)(Hot);

调用方法后会 dispatch 到 reducer 身上

  1. console.log(action) 发现有 type 和 payload 属性
  2. 在 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) => {
// console.log('action',action);
switch (action.type) {
case "GET_HOT_LIST":
return { ...state, hotList: action.payload.data.content };
default:
return { ...state };
}
};

export default hotReducer;

拿到数据后就可以渲染了