dva 是开发的 React 应用框架,将React-Router,Redux及异步操作Redux-saga三个 React 工具库包装在一起,简化了 API,让开发 React 应用更加方便和快捷。
数据变化的时机
数据的改变发生通常是通过用户交互行为或者浏览器行为(如路由跳转等)触发的,当此类行为会改变数据的时候可以通过 dispatch 发起一个 action,如果是同步行为会直接通过 Reducers 改变 State ,如果是异步行为(副作用)会先触发 Effects 然后流向 Reducers 最终改变 State,所以在 dva 中,数据流向非常清晰简明。
所以得出这个公式 =======》 dva = React-Router + Redux + Redux-saga
数据流模式
同步数据
异步数据
现在看看在dva里面怎么处理公共的数据仓库
实现效果
需要提醒的,项目已经安装好这三个工具,不用再安装。
核心概念
State:一个对象,保存整个应用状态View:React 组件构成的视图层Action:一个对象,描述事件connect 方法:一个函数,绑定 State 到 Viewdispatch 方法:一个函数,发送 Action 到 State
代码实现
routes/IndexPage.js的逻辑
import React from "react";
import { connect } from "dva";
import styles from "./IndexPage.css";
import PropTypes from "prop-types";
import { Button, Space } from "antd";
function IndexPage(props) {
const {
username,
count,
addCount,
decCount,
addCountAsync,
minusCountAsync,
} = props;
return (
Yay! Welcome to dva!
{username}
{count}
Add
Minus
Add async 2s
);
}
IndexPage.defaultProps = {
username: "admin",
count: 10,
};
IndexPage.propTypes = {
username: PropTypes.string,
count: PropTypes.number,
};
const matStateToProps = (state) => {
return {
count: state.products.count,
};
};
const mapDispatchToprops = (dispatch) => {
return {
addCount: () => dispatch({ type: "products/addCount" }),
decCount: () => dispatch({ type: "products/minusCount" }),
addCountAsync: () => dispatch({ type: "products/addCountAsync" }),
minusCountAsync: () => dispatch({ type: "products/minusCountAsync" }),
};
};
export default connect(matStateToProps, mapDispatchToprops)(IndexPage);
models/products.js的逻辑
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
export default {
namespace: "products",
state: {
count: 0,
lists: [
{ name: "dva", id: 1 },
{ name: "antd", id: 2 },
],
},
// 同步更新的方法
reducers: {
delete(state, { id }) {
return {
...state,
lists: state.lists.filter((item) => item.id !== id),
};
},
addCount(state) {
return { ...state, count: state.count + 1 };
},
minusCount(state) {
return { ...state, count: state.count - 1 };
},
},
effects: {
// *addCountAsync(action, effects) {
// const { put, select, call } = effects;
// const data = yield select();
// console.log("我被点击了");
// yield call(delay, 2000);
// yield put({ type: "addCount" });
// },
// 设置不同类型的监听器,监听器类型有takeLatest, takeEvery, throttle, debounce
addCountAsync: [
function* (action, effects) {
const { put, call } = effects;
yield call(delay, 2000);
yield put({ type: "addCount" });
},
{
type: "takeLatest",
},
],
*minusCountAsync(action, effects) {
const { put, call } = effects;
yield call(delay, 2000);
yield put({ type: "minusCount" });
},
},
};
**注意:**effects里面的getor方法默认的监听模式是takeEvery模式,也就是每次出发都会见听到,如下图
如果我们要更改模式,getor方法就要改写成如下
之前的,默认是takeEvery
*addCountAsync(action, effects) {
const { put, select, call } = effects;
const data = yield select();
console.log("我被点击了");
yield call(delay, 2000);
yield put({ type: "addCount" });
},
特定的监听模式
addCountAsync: [
function* (action, effects) {
const { put, call } = effects;
yield call(delay, 2000);
yield put({ type: "addCount" });
},
{
type: "takeLatest",
},
]
是不是很简单了,直接简化了之前单独引入三个工具库的代码,操作方便不少。
附上第二个实例的效果及代码
routes/Products .js
import React from "react";
import { connect } from "dva";
import ProductList from "../components/ProductList";
const Products = (props) => {
const { products, deleteProduct } = props;
return (
<>
List of Products
>
);
};
const mapStateToProps = (state) => {
return {
products: state.products.lists,
};
};
const mapDispatchToProps = (dispatch) => {
return {
deleteProduct: (id) => {
dispatch({ type: "products/delete", id });
},
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Products);
components/ProductList .js
import React from "react";
import PropTypes from "prop-types";
import { Table, Popconfirm, Button } from "antd";
const ProductList = ({ onDelete, products }) => {
const columns = [
{
title: "Name",
dataIndex: "name",
},
{
title: "Actions",
render: (text, record) => {
return (
);
},
},
];
return
};
ProductList.defaultProps = {
products: [],
};
ProductList.propTypes = {
onDelete: PropTypes.func.isRequired,
products: PropTypes.array.isRequired,
};
export default ProductList;
评论留言